﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Net;
using System.Runtime.Serialization.Json;
using System.Threading.Tasks;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Media;

namespace WellDone
{
    /// <summary>
    /// Main page used for ordering menu items.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        int iCurrentTableNumber = 0;
        bool bExclusive, bDoubleOptions;
        decimal decCurrentSubtotal = 0;
        int iCurrentOptionGroupIndex, iCurrentMenuItemID, iCurrentSplitSeatNumber, iIncludeOptions;
        List<Button> lstcategoryButton = new List<Button>();
        Dictionary<Button, Grid> dictNavMenuGroups = new Dictionary<Button, Grid>();
        Dictionary<Button, Grid> dictNavMenuCategories = new Dictionary<Button, Grid>();
        Dictionary<Button, ServiceReferenceOpenRPOS.MenuCategory> dictButtonMenuCategory = new Dictionary<Button, ServiceReferenceOpenRPOS.MenuCategory>();
        Dictionary<Button, ServiceReferenceOpenRPOS.MenuItem> dictButtonMenuItems = new Dictionary<Button, ServiceReferenceOpenRPOS.MenuItem>();
        Dictionary<string, ServiceReferenceOpenRPOS.MenuItem> dictOptionItems = new Dictionary<string, ServiceReferenceOpenRPOS.MenuItem>();
        List<OrderData> orderDataList = new List<OrderData>();
        List<int> orderSummaryIDList = new List<int>();
        OptionDialog currentOptionDialog;
        OrderData currentOrderData;
        Popup dialogPopup;
        ServiceReferenceOpenRPOS.MenuItemOptionGroup currentMenuItemOptionGroup;
        ServiceReferenceOpenRPOS.OrderSummary currentOrderSummary = new ServiceReferenceOpenRPOS.OrderSummary();
        ObservableCollection<OrderData> odl = new ObservableCollection<OrderData>();
        List<int> lstSeatNumber = new List<int>();
        bool isSplit = false;
        bool isMenuGroup = false;
        double dblNavGridWidth;
        double dblMenuGridHeight;
        double dblNavButtonWidth;
        TextBlock buttonTextBlock;
        int currentMenuGroupButton = 0, currentButton = 0,currentMenuCategoryButton=0;
        public MainPage()
        {
            // Initialize...
            this.InitializeComponent();
            GetMenuGroup();
            int iNavButtonCount = Globals.MenuCategoryRecords.Count();
            dblMenuGridHeight = Windows.UI.Xaml.Window.Current.Bounds.Height - rowTopMargin.Height.Value - rowNav.Height.Value - rowButtonBar.Height.Value - rowBottomMargin.Height.Value;
            dblNavButtonWidth = Globals.k_dbl_nav_button_width;

            currentOrderSummary.col_Status = Globals.k_int_status_open;

            //isMenuGroup = false;

            if (isMenuGroup == true)
            {
                IsMenuGroup();
            }
            else if (isMenuGroup == false)
            {
                IsMenuCategory();
            }

            // Adjust the height of the order list...
            lvCurrentOrder.Height = dblMenuGridHeight - (tblkSubtotal.Height * 3);
            // Hide the manager button if the current user is not a manager
            btnManager.Visibility = (Globals.currentLogin.col_Manager ? Visibility.Visible : Visibility.Collapsed);
            btnOpenDrawer.Visibility = (Globals.currentLogin.col_Manager ? Visibility.Visible : Visibility.Collapsed);
            // Display current username
            tblkStatus.Text = Globals.currentLogin.col_DisplayName;
            // Determine if table layout should be displayed initially...
            if (Globals.defaultTableView) btnFindTable_Click(this, null);
            // Determine whether or not to show the close and print buttons
            try
            {
                var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
                string value = (string)localSettings.Values[Globals.k_str_settings_show_close_button].ToString().ToUpper().Trim();
                btnClose.Visibility = (value == Globals.k_str_value_yes || value == Globals.k_str_value_true || value == Globals.k_str_value_one)
                    ? Visibility.Visible : Visibility.Collapsed;
                value = localSettings.Values[Globals.k_str_settings_show_print_button].ToString().ToUpper().Trim();
                btnPrint.Visibility = (value == Globals.k_str_value_yes || value == Globals.k_str_value_true || value == Globals.k_str_value_one)
                    ? Visibility.Visible : Visibility.Collapsed;
            }
            catch (Exception) { }
        }

        private void GetMenuGroup()
        {
            Globals.ConfigurationRecords = Globals.client.GetConfigurationObjectsAsync(Globals.token, "KeyName='UseMenuGroups'").Result;
            if (Globals.ConfigurationRecords.Count > 0)
            {
                isMenuGroup = Convert.ToBoolean(Globals.ConfigurationRecords[0].col_Value.Trim().ToLower());
            }
        }

        private void IsMenuGroup()
        {
            LayoutRoot.ColumnDefinitions[3].Width = new GridLength(135);
            dblNavGridWidth = (Windows.UI.Xaml.Window.Current.Bounds.Width - (2 * colLeftMargin.Width.Value) - colOrder.Width.Value - (2 * colRightMargin.Width.Value) - Globals.k_dbl_menu_button_width);
            GetMenuGroupRecord();
            buttonTextBlock = new TextBlock();
            buttonTextBlock.TextWrapping = TextWrapping.Wrap;
            buttonTextBlock.TextAlignment = TextAlignment.Center;
            /* This code for Menu Group Text Rotation */
            //RotateTransform rt = new RotateTransform();
            //rt.Angle = 270;
            //rt.CenterX = 50;
            //rt.CenterY = 5;
            //buttonTextBlock.RenderTransform = rt;
            buttonTextBlock.Text = Globals.k_str_no_menu_group;
            btnnoGroup.Content = buttonTextBlock;
            btnnoGroup.FontSize = Globals.k_dbl_nav_button_font_size;
            btnnoGroup.Style = (Style)this.Resources["ButtonStyleMain"];
            btnnoGroup.IsEnabled = false;
            Grid.SetColumn(btnLogout, 3);
            ShowMenuCategory();
        }

        private void IsMenuCategory()
        {
            LayoutRoot.ColumnDefinitions[3].Width = new GridLength(0);
            dblNavGridWidth = Windows.UI.Xaml.Window.Current.Bounds.Width - (2 * colLeftMargin.Width.Value) - colOrder.Width.Value - (2 * colRightMargin.Width.Value);
            GetMenuCategoryRecord(false);
            Grid.SetColumn(btnLogout, 2);
        }


        private void GetMenuCategoryRecord(bool noGroupID)
        {
            currentButton = 0;
            ObservableCollection<ServiceReferenceOpenRPOS.MenuCategory> lstCategories = Globals.MenuCategoryRecords;
            
            if (noGroupID)
            {
                lstCategories = Globals.MenuCategoryNoGroupRecords;
            }
            
            foreach (ServiceReferenceOpenRPOS.MenuCategory mc in lstCategories)
            {
                Button navButton = new Button();
                navButton.Tag = mc.col_ID;
                navButton.IsEnabled = (currentButton != 0);
                navButton.Margin = new Thickness(colLeftMargin.Width.Value + (dblNavButtonWidth * currentButton++), rowTopMargin.Height.Value, 0, 0);
                navButton.Width = dblNavButtonWidth;
                navButton.Height = rowNav.Height.Value;
                buttonTextBlock = new TextBlock();
                buttonTextBlock.TextWrapping = TextWrapping.Wrap;
                buttonTextBlock.TextAlignment = TextAlignment.Center;
                buttonTextBlock.Text = mc.col_Name;
                navButton.Content = buttonTextBlock;
                navButton.FontSize = Globals.k_dbl_nav_button_font_size;
                navButton.Click += new RoutedEventHandler(OnNavButtonClick);
                navButton.Style = (Style)this.Resources["ButtonStyleMain"];

                grdNav.Children.Add(navButton);
                // Create a grid for this menu category
                Grid grdMenuCategory = new Grid();
                var count = Globals.MenuItemRecords.Where(x => x.col_MenuCategoryID == mc.col_ID).Count();
                // Add buttons for items in each menu category
                if (count > 0)
                {
                    int hbuttons = (int)Math.Sqrt(count);
                    int vbuttons = count / hbuttons;
                    int hcnt = 0, vcnt = 0, cnt = 0;
                    vbuttons = (count > (hbuttons * vbuttons)) ? vbuttons + 1 : vbuttons;
                    double dblButtonWidth = (dblNavGridWidth / hbuttons) - colLeftMargin.Width.Value;
                    double dblButtonHeight = (dblMenuGridHeight / vbuttons) - colRightMargin.Width.Value;
                    foreach (ServiceReferenceOpenRPOS.MenuItem mi in Globals.MenuItemRecords.Where(x => x.col_MenuCategoryID == mc.col_ID))
                    {
                        Button btn = new Button();
                        // Size and position buttons such that they fit evenly on the screen
                        hcnt = cnt % hbuttons;
                        vcnt = cnt / hbuttons;
                        buttonTextBlock = new TextBlock();
                        buttonTextBlock.TextWrapping = TextWrapping.Wrap;
                        buttonTextBlock.TextAlignment = TextAlignment.Center;
                        buttonTextBlock.Text = mi.col_FullName;
                        btn.Content = buttonTextBlock;
                        btn.Margin = new Thickness(hcnt * dblButtonWidth + ((hcnt + 1) * colLeftMargin.Width.Value) + (colLeftMargin.Width.Value / hbuttons) + 1,
                            vcnt * dblButtonHeight + ((vcnt + 1) * rowTopMargin.Height.Value), 0, 0);
                        btn.Width = dblButtonWidth;
                        btn.Height = dblButtonHeight;
                        btn.HorizontalAlignment = HorizontalAlignment.Left;
                        btn.VerticalAlignment = VerticalAlignment.Top;
                        if (Windows.UI.Xaml.Window.Current.Bounds.Width == 1024)
                            btn.FontSize = 14;
                        else
                            if (vbuttons < Globals.k_int_small_rows)
                                btn.FontSize = Globals.k_dbl_menu_button_font_size;
                            else
                                btn.FontSize = Globals.k_dbl_menu_small_button_font_size;
                        dictButtonMenuItems[btn] = mi;
                        btn.Click += new RoutedEventHandler(OnMenuItemButtonClick);
                        btn.Background = new SolidColorBrush(Windows.UI.Colors.LightBlue);
                        btn.Style = (Style)this.Resources["ButtonStyleMain"];
                        grdMenuCategory.Children.Add(btn);
                        cnt++;
                    }
                }
                if (currentButton == 1)
                {
                    grdMenu.Children.Clear();
                    grdMenu.Children.Add(grdMenuCategory);
                }
                // Add this grid to the collection
                dictNavMenuCategories.Add(navButton, grdMenuCategory);
            }
        }

        private void GetMenuGroupRecord()
        {
            int menugroup = Globals.k_dbl_menugroup_button_margin;
            foreach (ServiceReferenceOpenRPOS.MenuGroup mg in Globals.MenuGroupRecords)
            {
                Button grpButton = new Button();
                grpButton.Width = Globals.k_dbl_menugroup_button_width;
                grpButton.Height = Globals.k_dbl_menugroup_button_height;
                grpButton.VerticalAlignment = Windows.UI.Xaml.VerticalAlignment.Top;
                grpButton.Margin = new Thickness(0, menugroup, 0, 0);
                buttonTextBlock = new TextBlock();

                /* This code for Menu Group Text Rotation */
                //RotateTransform rt = new RotateTransform();
                //rt.Angle = 270;
                //rt.CenterX = 50;
                //rt.CenterY = 5;
                //buttonTextBlock.RenderTransform = rt;
                buttonTextBlock.TextWrapping = TextWrapping.Wrap;
                buttonTextBlock.TextAlignment = TextAlignment.Justify;
                buttonTextBlock.Text = mg.col_Name;
                grpButton.Content = buttonTextBlock;
               
                grpButton.FontSize = Globals.k_dbl_nav_button_font_size;
                grpButton.Click += new RoutedEventHandler(OnMenuGroupButtonClick);
                grpButton.Style = (Style)this.Resources["ButtonStyleMain"];
                grdGroup.Children.Add(grpButton);
                menugroup = menugroup + 120;
                currentMenuGroupButton++;

                // Create a grid for this menu group

                Grid grdMenugroup = new Grid();

                var Groupcount = Globals.MenuCategoryRecords.Where(x => x.col_MenuGroupID == mg.col_ID).Count();
                currentButton = 0;
                foreach (ServiceReferenceOpenRPOS.MenuCategory mc in Globals.MenuCategoryRecords.Where(x => x.col_MenuGroupID == mg.col_ID))
                {
                    Button navButton = new Button();
                    navButton.Tag = mc.col_ID;
                    navButton.IsEnabled = (currentButton != 0);
                    navButton.Margin = new Thickness(colLeftMargin.Width.Value + (dblNavButtonWidth * currentButton++), rowTopMargin.Height.Value, 0, 0);
                    navButton.Width = dblNavButtonWidth;
                    navButton.Height = rowNav.Height.Value;
                    buttonTextBlock = new TextBlock();
                    buttonTextBlock.TextWrapping = TextWrapping.Wrap;
                    buttonTextBlock.TextAlignment = TextAlignment.Center;
                    buttonTextBlock.Text = mc.col_Name;
                    navButton.Content = buttonTextBlock;
                    navButton.FontSize = Globals.k_dbl_nav_button_font_size;
                    navButton.Click += new RoutedEventHandler(OnNavMenuButtonClick);
                    navButton.Style = (Style)this.Resources["ButtonStyleMain"];
                    grdMenugroup.Children.Add(navButton);
                    lstcategoryButton.Add(navButton);
                   
                    // Create a grid for this menu group
                    Grid grdMenuCategory = new Grid();

                    var count = Globals.MenuItemRecords.Where(x => x.col_MenuCategoryID == mc.col_ID).Count();

                    if (count > 0)
                    {
                        int hbuttons = (int)Math.Sqrt(count);
                        int vbuttons = count / hbuttons;
                        int hcnt = 0, vcnt = 0, cnt = 0;
                        vbuttons = (count > (hbuttons * vbuttons)) ? vbuttons + 1 : vbuttons;
                        double dblButtonWidth = (dblNavGridWidth / hbuttons) - colLeftMargin.Width.Value;
                        double dblButtonHeight = (dblMenuGridHeight / vbuttons) - colRightMargin.Width.Value;
                        foreach (ServiceReferenceOpenRPOS.MenuItem mi in Globals.MenuItemRecords.Where(x => x.col_MenuCategoryID == mc.col_ID))
                        {
                            Button btn = new Button();
                            // Size and position buttons such that they fit evenly on the screen
                            hcnt = cnt % hbuttons;
                            vcnt = cnt / hbuttons;
                            buttonTextBlock = new TextBlock();
                            buttonTextBlock.TextWrapping = TextWrapping.Wrap;
                            buttonTextBlock.TextAlignment = TextAlignment.Center;
                            buttonTextBlock.Text = mi.col_FullName;
                            btn.Content = buttonTextBlock;
                            btn.Margin = new Thickness(hcnt * dblButtonWidth + ((hcnt + 1) * colLeftMargin.Width.Value) + (colLeftMargin.Width.Value / hbuttons) + 1,
                                vcnt * dblButtonHeight + ((vcnt + 1) * rowTopMargin.Height.Value), 0, 0);
                            btn.Width = dblButtonWidth;
                            btn.Height = dblButtonHeight;
                            btn.HorizontalAlignment = HorizontalAlignment.Left;
                            btn.VerticalAlignment = VerticalAlignment.Top;
                            if (Windows.UI.Xaml.Window.Current.Bounds.Width == 1024)
                                btn.FontSize = 14;
                            else
                                if (vbuttons < Globals.k_int_small_rows)
                                    btn.FontSize = Globals.k_dbl_menu_button_font_size;
                                else
                                    btn.FontSize = Globals.k_dbl_menu_small_button_font_size;
                            dictButtonMenuItems[btn] = mi;
                            btn.Click += new RoutedEventHandler(OnMenuItemButtonClick);
                            btn.Background = new SolidColorBrush(Windows.UI.Colors.LightBlue);
                            btn.Style = (Style)this.Resources["ButtonStyleMain"];
                            grdMenuCategory.Children.Add(btn);
                            cnt++;
                        }
                    }

                    dictNavMenuCategories.Add(navButton, grdMenuCategory);
                    currentMenuCategoryButton++;

                    if (currentMenuCategoryButton == 1)
                    {
                        grdMenu.Children.Clear();
                        grdMenu.Children.Add(grdMenuCategory);
                    }
                }

                if (currentMenuGroupButton == 1)
                {
                    grdNav.Children.Clear();
                    grdNav.Children.Add(grdMenugroup);
                }

                dictNavMenuGroups.Add(grpButton, grdMenugroup);
            }
        }

        private void OnMenuGroupButtonClick(object sender, RoutedEventArgs e)
        {
            // Disable selected button
            Button clickedButton = (Button)sender;
           
            // Enable all other nav buttons
            foreach (Button navButton in grdGroup.Children)
            {
               navButton.IsEnabled = true;
            }

            clickedButton.IsEnabled = false;

            // Display selected grid
            grdNav.Children.Clear();
            grdNav.Children.Add(dictNavMenuGroups[clickedButton]);
            OnNavMenuButtonClick(dictNavMenuGroups[clickedButton].Children[0], e);
        }

        private void OnNavMenuButtonClick(object sender, RoutedEventArgs e)
        {
            // Disable selected button
            Button clickedButton = (Button)sender;
            // Enable all other nav buttons
            foreach (Button navButton in lstcategoryButton)
            {
                navButton.IsEnabled = true;
            }

            if (clickedButton!=null)
            {
                clickedButton.IsEnabled = false;

                // Display selected grid
                grdMenu.Children.Clear();
                grdMenu.Children.Add(dictNavMenuCategories[clickedButton]);
            }
            else
            {
                grdMenu.Children.Clear();
            }
        }

        private void OnNavButtonClick(object sender, RoutedEventArgs e)
        {
            Button clickedButton = (Button)sender;
            clickedButton.IsEnabled = false;
            // Enable all other nav buttons
            foreach (Button navButton in grdNav.Children)
            {
                if (navButton != clickedButton)
                    navButton.IsEnabled = true;
            }
            // Display selected grid
            grdMenu.Children.Clear();
            grdMenu.Children.Add(dictNavMenuCategories[clickedButton]);
        }

        private void btnNoGroup_Click(object sender, RoutedEventArgs e)
        {
            ShowMenuCategory(); 
        }


        private void ShowMenuCategory()
        {
            grdNav.Children.Clear();
            grdMenu.Children.Clear();
            GetMenuCategoryRecord(true);
            if (grdGroup.Children.Count > 0)
            {
                foreach (Button navButton in grdGroup.Children)
                {
                    navButton.IsEnabled = true;
                }
            }
            btnnoGroup.IsEnabled = false;
        }

        private void addOrderItem(OrderData od, bool bUpdateTotals = true)
        {
            lvCurrentOrder.ItemsSource = null;
            odl.Add(od);
            lvCurrentOrder.ItemsSource = odl;
            lvCurrentOrder.ScrollIntoView(od);
            if (bUpdateTotals) updateTotals();
        }

        // Get Special Price for different Interval
        private async Task<decimal> getCurrentPrice(int MenuItemId, decimal Price)
        {
            // Exit if it is determined that there are no special prices for selected menu item
            if (Globals.TimePriceRecords.Where(x => x.col_MenuItemID == MenuItemId).Count() == 0) return Price;

            DateTime localTime = await Globals.Now();
            var Item_TimePrices = Globals.TimePriceRecords.Where(x => x.col_MenuItemID == MenuItemId);
            foreach (ServiceReferenceOpenRPOS.TimePrice tp in Item_TimePrices)
            {
                if (tp != null)
                {
                    switch (tp.col_Interval)
                    {
                        case Globals.k_int_time_interval_once:
                            if (localTime >= tp.col_Start && localTime <= tp.col_Stop) return tp.col_Price;
                            break;
                        case Globals.k_int_time_interval_daily:
                            if (localTime.TimeOfDay >= tp.col_Start.TimeOfDay && localTime.TimeOfDay <= tp.col_Stop.TimeOfDay) return tp.col_Price;
                            break;
                        case Globals.k_int_time_interval_weekly:
                            if (tp.col_Start.DayOfWeek == localTime.DayOfWeek)
                                if (localTime.TimeOfDay >= tp.col_Start.TimeOfDay && localTime.TimeOfDay <= tp.col_Stop.TimeOfDay) return tp.col_Price;
                            break;
                        case Globals.k_int_time_interval_monthly:
                            if (tp.col_Start.Day == localTime.Day)
                                if (localTime.TimeOfDay >= tp.col_Start.TimeOfDay && localTime.TimeOfDay <= tp.col_Stop.TimeOfDay) return tp.col_Price;
                            break;
                    }
                }
            }
            return Price;
        }

        private async void OnMenuItemButtonClick(object sender, RoutedEventArgs e)
        {
            Button btn = (Button)sender;
            // Add item to order
            OrderData od = new OrderData();
            od.SeatNumber = findSeatNumber(); //get seat number to save with newly added menu item, if payment is started.
            od.MenuItemID = dictButtonMenuItems[btn].col_ID;
            od.MenuItemName = dictButtonMenuItems[btn].col_FullName;
            od.Price = await getCurrentPrice(od.MenuItemID, dictButtonMenuItems[btn].col_Price);
            od.DisplayPrice = od.Price.ToString("N");
            decCurrentSubtotal += od.Price;
            currentOrderSummary.col_Subtotal = decCurrentSubtotal;// += od.Price;
            addOrderItem(od);
            btnSend.IsEnabled = true;
            btnClose.IsEnabled = false;

            btnNew.IsEnabled = true;
            // Handle pizzas differently...
            if (dictButtonMenuItems[btn].col_Pizza)
            {
                PizzaDialog pd = new PizzaDialog();
                pd.Width = Windows.UI.Xaml.Window.Current.Bounds.Width;
                pd.Height = Windows.UI.Xaml.Window.Current.Bounds.Height;
                pd.iParentMenuItemID = od.MenuItemID;
                pd.init();
                pd.CloseRequested += PizzaDialog_CloseRequested;
                od.Options = new List<OrderData>();
                od.Options.Clear();
                currentOrderData = od;
                dialogPopup = new Popup();
                dialogPopup.Child = pd;
                dialogPopup.IsOpen = true;
            }
            else // Non-pizza
            {
                // Determine if any option groups exist...
                if (Globals.MenuItemOptionGroupRecords.Where(x => x.col_MenuItemID == dictButtonMenuItems[btn].col_ID).Count() > 0)
                {
                    iCurrentOptionGroupIndex = 0;
                    iCurrentMenuItemID = dictButtonMenuItems[btn].col_ID;
                    iIncludeOptions = dictButtonMenuItems[btn].col_IncludeOptions;
                    bDoubleOptions = dictButtonMenuItems[btn].col_DoubleOptions;
                    currentMenuItemOptionGroup = Globals.MenuItemOptionGroupRecords.Where(x => x.col_MenuItemID == iCurrentMenuItemID).ElementAt(iCurrentOptionGroupIndex++);
                    od.Options = new List<OrderData>();
                    od.Options.Clear();
                    currentOrderData = od;
                    createOptionGroupDialog();
                }
            }
        }

        private void PizzaDialog_CloseRequested(object sender, EventArgs e)
        {
            dialogPopup.IsOpen = false;
            // Update slip with pizza information...
            PizzaDialog pd = (PizzaDialog)sender;
            foreach (OrderData od in pd.orderDataList)
            {
                od.MenuItemName = "  " + od.MenuItemName;
                od.Parent = currentOrderData;
                currentOrderData.Options.Add(od);
                decCurrentSubtotal += od.Price;
                addOrderItem(od);
            }
        }

        private async void btnLogout_Click(object sender, RoutedEventArgs e)
        {
            // Prompt the user before logging out
            var messageDialog = new MessageDialog("Are you sure you want to logout?");
            // Add commands and set their callbacks; both buttons use the same callback function instead of inline event handlers
            IUICommand icmdYes = new UICommand("Yes");
            IUICommand icmdNo = new UICommand("No");
            messageDialog.Commands.Add(icmdYes);
            messageDialog.Commands.Add(icmdNo);
            // Show the message dialog
            if (await messageDialog.ShowAsync() == icmdYes)
            {
                updatePunchStatus();
            }
        }


        private async void updatePunchStatus()
        {
            if (Globals.timeclockbtnEnable && Globals.timeclockEnable)
            {
                Globals.TimeSheetRecords = await Globals.client.GetTimeSheetObjectsAsync(Globals.token, "");
                DateTime dtNow = await Globals.Now();
                IEnumerable<ServiceReferenceOpenRPOS.TimeSheet> query = Globals.TimeSheetRecords.Where(x => x.col_EmployeeID == Globals.currentLogin.col_ID &&
                             x.col_PunchDateTime.Date == dtNow.Date && x.col_Adjusted == false);

                if (query.Count() > 0)
                {
                    if (query.Last().col_PunchType == true)
                    {

                        // Time Clock Dialog...
                        TimeClockDialog tcd = new TimeClockDialog();
                        tcd.Width = Windows.UI.Xaml.Window.Current.Bounds.Width;
                        tcd.Height = Windows.UI.Xaml.Window.Current.Bounds.Height;
                        tcd.CloseRequested += TimeClockDialog_CloseRequested;
                        dialogPopup = new Popup();
                        dialogPopup.Child = tcd;
                        dialogPopup.IsOpen = true;
                    }
                }
            }

            // Return to the login screen...
            Frame rootFrame = Window.Current.Content as Frame;
            rootFrame.Navigate(typeof(Login));
        }

        private void TimeClockDialog_CloseRequested(object sender, EventArgs e)
        {
            // Close the dialog...
            dialogPopup.IsOpen = false;
        }

        void createOptionGroupDialog()
        {
            string itemName;
            OptionDialog od = new OptionDialog();
            od.Width = Windows.UI.Xaml.Window.Current.Bounds.Width;
            od.Height = Windows.UI.Xaml.Window.Current.Bounds.Height;
            Dictionary<string, int> dictMenuItems = new Dictionary<string, int>();
            Dictionary<string, bool> dictMenuItemChecked = new Dictionary<string, bool>();
            ServiceReferenceOpenRPOS.OptionGroup og = Globals.OptionGroupRecords.Where(x => x.col_ID == currentMenuItemOptionGroup.col_OptionGroupID).First();
            dictOptionItems.Clear();
            // Determine the number of options
            foreach (ServiceReferenceOpenRPOS.MenuOption mo in Globals.MenuOptionRecords.Where(x => x.col_OptionGroupID == currentMenuItemOptionGroup.col_OptionGroupID))
            {
                if (Globals.MenuItemRecords.Where(x => x.col_ID == mo.col_MenuItemID).Count() > 0)
                {
                    ServiceReferenceOpenRPOS.MenuItem mi = Globals.MenuItemRecords.Where(x => x.col_ID == mo.col_MenuItemID).First();
                    itemName = mi.col_FullName;
                    if (itemName.Contains("("))
                        itemName = itemName.Substring(0, itemName.IndexOf("("));
                    dictMenuItems.Add(itemName, mi.col_ID);
                    dictOptionItems.Add(itemName, mi);
                    dictMenuItemChecked.Add(itemName, mo.col_Checked);
                }
            }
            // Display options in alphabetical order
            var list = dictMenuItems.Keys.ToList();
            list.Sort();
            int cnt = 0;
            bExclusive = og.col_Exclusive;
            double dblScale = 2;
            double dblCheckboxHeight = (list.Count() < 10) ? Globals.k_dbl_checkbox_height : Globals.k_dbl_small_checkbox_height;
            int iNumCols = ((list.Count() - 1) / Globals.k_int_max_options_per_column) + 1;
            int iCurrCol = 0;
            // Iterate over the options in the group
            foreach (var key in list)
            {
                // Double the size of the options for easier selection
                ScaleTransform st = new ScaleTransform();
                st.ScaleX = dblScale;
                st.ScaleY = dblScale;
                // Use radio buttons for an exclusive option group
                if (bExclusive)
                {
                    RadioButton rb = new RadioButton();
                    rb.Content = key;
                    rb.Height = Globals.k_dbl_radio_button_height;
                    if (cnt == 0) rb.IsChecked = true;
                    rb.Margin = new Thickness(Globals.k_dbl_button_spacing + (iCurrCol * Globals.k_dbl_option_group_width),
                        (cnt * Globals.k_dbl_radio_button_height * dblScale) + Globals.k_dbl_radio_button_height, 0, 0);
                    rb.Padding = new Thickness(Globals.k_dbl_option_padding, Globals.k_dbl_option_padding, 0, 0);
                    rb.HorizontalAlignment = HorizontalAlignment.Left;
                    rb.VerticalAlignment = VerticalAlignment.Top;
                    rb.RenderTransform = st;
                    od.addUIElement(rb);
                    iCurrCol = (iCurrCol + 1) % iNumCols;
                    cnt = (iCurrCol == 0) ? cnt + 1 : cnt;
                }
                else // Used check-box for non-exclusive (multiple options allowed) group
                {
                    CheckBox cb = new CheckBox();
                    cb.Content = key;
                    cb.Height = dblCheckboxHeight;
                    cb.Margin = new Thickness(Globals.k_dbl_button_spacing + (iCurrCol * Globals.k_dbl_option_group_width),
                        (cnt * Globals.k_dbl_checkbox_height * dblScale) + Globals.k_dbl_checkbox_height, 0, 0);
                    cb.Padding = new Thickness(Globals.k_dbl_option_padding, Globals.k_dbl_option_padding, 0, 0);
                    cb.RenderTransform = st;
                    cb.IsChecked = dictMenuItemChecked[key];
                    cb.IsThreeState = bDoubleOptions;
                    cb.HorizontalAlignment = HorizontalAlignment.Left;
                    cb.VerticalAlignment = VerticalAlignment.Top;
                    od.addUIElement(cb);
                    iCurrCol = (iCurrCol + 1) % iNumCols;
                    cnt = (iCurrCol == 0) ? cnt + 1 : cnt;
                }
            }
            // Size the dialog
            od.innerDialog.Width = (Globals.k_dbl_option_group_width * iNumCols) + (2 * Globals.k_dbl_button_spacing);
            cnt = (list.Count() < Globals.k_int_max_options_per_column) ? list.Count() : (list.Count() / iNumCols);
            cnt += ((list.Count() % iNumCols) == 0) ? 0 : 1;
            od.innerDialog.Height = dblScale * cnt * (og.col_Exclusive ? Globals.k_dbl_radio_button_height : Globals.k_dbl_checkbox_height) + Globals.k_dbl_option_group_min_height;
            currentOptionDialog = od;
            od.CloseRequested += Dialog_CloseRequested;
            dialogPopup = new Popup();
            dialogPopup.Child = od;
            dialogPopup.IsOpen = true;
        }

        private bool isDefaultOption(int optionGroupID, int optionMenuItemID)
        {
            return Globals.MenuOptionRecords.Where(x => x.col_OptionGroupID == optionGroupID && x.col_MenuItemID == optionMenuItemID).First().col_Checked;
        }

        private void Dialog_CloseRequested(object sender, EventArgs e)
        {
            dialogPopup.IsOpen = false;
            int cnt = 0;
            string strDbl;
            // Add selected options...
            if (bExclusive)
            {
                // Identify the selected item
                foreach (UIElement uie in currentOptionDialog.innerDialog.Children)
                {
                    if (uie.GetType().ToString().Contains("RadioButton"))
                    {
                        RadioButton rb = (RadioButton)uie;
                        if (rb.IsChecked == true) // Selected
                        {
                            // Add item to order
                            OrderData od = new OrderData();
                            od.MenuItemID = dictOptionItems[rb.Content.ToString()].col_ID;
                            od.MenuItemName = "  " + dictOptionItems[rb.Content.ToString()].col_FullName;
                            od.DisplayPrice = (dictOptionItems[rb.Content.ToString()].col_Price > 0 ? dictOptionItems[rb.Content.ToString()].col_Price.ToString("N") : "");
                            od.Price = dictOptionItems[rb.Content.ToString()].col_Price;
                            od.Exclusive = true;
                            od.Parent = currentOrderData;
                            currentOrderData.Options.Add(od);
                            decCurrentSubtotal += od.Price;
                            addOrderItem(od);
                        }
                    }
                }
            }
            else
            {
                // Identify the selected item
                foreach (UIElement uie in currentOptionDialog.innerDialog.Children)
                {
                    if (uie.GetType().ToString().Contains("CheckBox"))
                    {
                        CheckBox cb = (CheckBox)uie;
                        if (cb.IsChecked != false) // Selected
                        {
                            // Determine if this is a default option
                            if (!Globals.MenuOptionRecords.Where(x => x.col_OptionGroupID == currentMenuItemOptionGroup.col_OptionGroupID
                                && x.col_MenuItemID == dictOptionItems[cb.Content.ToString()].col_ID).First().col_Checked)
                            {
                                // Add item to order
                                OrderData od = new OrderData();
                                od.MenuItemID = dictOptionItems[cb.Content.ToString()].col_ID;
                                if (iIncludeOptions <= cnt++)
                                    od.Price = dictOptionItems[cb.Content.ToString()].col_Price;
                                strDbl = "";

                                // Check for "double"
                                if (bDoubleOptions && cb.IsChecked == null)
                                {
                                    cnt++;
                                    od.Price += dictOptionItems[cb.Content.ToString()].col_Price;
                                    strDbl = "Double ";
                                }

                                od.DisplayPrice = (od.Price > 0 ? od.Price.ToString("N") : "");
                                od.MenuItemName = "  Add " + strDbl + dictOptionItems[cb.Content.ToString()].col_FullName;
                                od.Exclusive = false;
                                od.Parent = currentOrderData;
                                decCurrentSubtotal += od.Price;
                                currentOrderData.Options.Add(od);
                                addOrderItem(od);
                            }
                        }
                        else if (Globals.MenuOptionRecords.Where(x => x.col_OptionGroupID == currentMenuItemOptionGroup.col_OptionGroupID
                              && x.col_MenuItemID == dictOptionItems[cb.Content.ToString()].col_ID).First().col_Checked)
                        // Handle the case where the default option is un-selected
                        {
                            OrderData od = new OrderData();
                            od.MenuItemID = dictOptionItems[cb.Content.ToString()].col_ID;
                            od.MenuItemName = "  No " + dictOptionItems[cb.Content.ToString()].col_FullName;
                            od.DisplayPrice = "";
                            od.Price = 0;
                            od.Exclude = true;
                            od.Exclusive = false;
                            od.Parent = currentOrderData;
                            decCurrentSubtotal += od.Price;
                            currentOrderData.Options.Add(od);
                            addOrderItem(od);
                        }
                    }
                }
            }
            // Determine if another option dialog needs to be displayed
            if (Globals.MenuItemOptionGroupRecords.Where(x => x.col_MenuItemID == iCurrentMenuItemID).Count() > iCurrentOptionGroupIndex)
            {
                // Display the next option group
                currentMenuItemOptionGroup = Globals.MenuItemOptionGroupRecords.Where(x => x.col_MenuItemID == iCurrentMenuItemID).ElementAt(iCurrentOptionGroupIndex++);
                createOptionGroupDialog();
            }
        }


        private void lvCurrentOrder_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (lvCurrentOrder.SelectedItems.Count > 0)
            {
                foreach (OrderData od in lvCurrentOrder.SelectedItems)
                {
                    // Do not allow exclusive options or discounts to be deleted from the list...
                    if (od.Exclusive || (od.MenuItemID == 0 && od.OpenItemID == 0))
                        lvCurrentOrder.SelectedItems.Remove(od);
                    // Only allow managers to remove items that have already been sent
                    if (!Globals.currentLogin.col_Manager)
                        if (od.Sent)
                            lvCurrentOrder.SelectedItems.Remove(od);
                }
                btnDelete.IsEnabled = lvCurrentOrder.SelectedItems.Count() > 0;
            }
            else btnDelete.IsEnabled = false;
        }


        private async void recalculateTotal()
        {
            decCurrentSubtotal = 0;
            foreach (OrderData od in lvCurrentOrder.Items)
            {
                if (od.MenuItemID > 0)
                {
                    decCurrentSubtotal += od.Price;
                    // Determine if there's a discount associated with this item.  If so, apply it...
                    if (od.DiscountID > 0)
                    {
                        // Check for discount...
                        Globals.DiscountRecords = await Globals.client.GetDiscountObjectsAsync(Globals.token, "ID=" + od.DiscountID);
                        if (Globals.DiscountRecords.Count > 0)
                        {
                            decimal dCurrentDiscount;
                            if (Globals.DiscountRecords[0].col_IsPercent)
                            {
                                decimal dCurrentAmount = od.Price;
                                // Be sure to include subitems as part of the discount total
                                foreach (OrderData odi in lvCurrentOrder.Items)
                                    if (odi.Parent == od)
                                        dCurrentAmount += odi.Price;
                                dCurrentDiscount = Math.Round((decimal)(dCurrentAmount * (Globals.DiscountRecords[0].col_Amount / 100)), 2);
                            }
                            else
                                dCurrentDiscount = Globals.DiscountRecords[0].col_Amount;
                            decCurrentSubtotal -= dCurrentDiscount;
                        }

                    }
                }
            }
            updateTotals();
        }


        private async Task<Boolean> showNetworkErrorDialog()
        {
            // Prompt the user before logging out
            var messageDialog = new MessageDialog("A network error has occurred.");
            // Add commands and set their callbacks; both buttons use the same callback function instead of inline event handlers
            IUICommand icmdTryAgain = new UICommand("Try Again");
            messageDialog.Commands.Add(icmdTryAgain);
            messageDialog.Commands.Add(new UICommand("Close"));
            // Log error...
            await Globals.client.AppendToLogAsync(Globals.token, Globals.strExceptionMessage);
            Globals.strExceptionMessage = "";
            // Show the message dialog
            return (await messageDialog.ShowAsync() == icmdTryAgain);
        }


        private async void promptNetworkErrorOnSend()
        {
            if (await showNetworkErrorDialog())
                await sendOrder();
        }


        private async void promptNetworkErrorOnClose()
        {
            if (await showNetworkErrorDialog())
                await closeCurrentOrder();
        }


        private async void promptNetworkErrorOnGetOpenOrders()
        {
            if (await showNetworkErrorDialog())
                await getOpenOrders();
        }


        private async void promptNetworkErrorOnOpenOrdersSelectionChanged()
        {
            if (await showNetworkErrorDialog())
                cmbOpenOrders_SelectionChanged(null, null);
        }

        private int findSeatNumber()
        {
            int tmpCount = 0;
            if (Globals.OrderCheckRecords.Count > 0)
            {
                for (int j = 0; j < Globals.OrderCheckRecords.Count; j++)
                {
                    if (Globals.OrderCheckRecords[j].col_SeatNumber == tmpCount) tmpCount++;
                    else return tmpCount;
                }
            }
            return tmpCount;
        }

        private async Task<Boolean> sendOrder(bool bFilterStatus = true, bool bPrint = true)
        {
            btnSend.IsEnabled = false;
            btnSplit.IsEnabled = true;
            // Display the wait page...
            WaitPage waitPage = new WaitPage();
            waitPage.Width = Windows.UI.Xaml.Window.Current.Bounds.Width;
            waitPage.Height = Windows.UI.Xaml.Window.Current.Bounds.Height;
            dialogPopup = new Popup();
            dialogPopup.Child = waitPage;
            dialogPopup.IsOpen = true;
            // Determine if this is a new order
            if (currentOrderSummary.col_Status == Globals.k_int_status_open)
            {
                currentOrderSummary.bFilterStatus = bFilterStatus;
                currentOrderSummary.bFilterTimeOpened = true;
                currentOrderSummary.bFilterLoginID = true;
                currentOrderSummary.bFilterSplit = true;
                currentOrderSummary.bFilterSplitEvenly = true;
                currentOrderSummary.col_LoginID = Globals.currentLogin.col_ID;
                currentOrderSummary.col_TimeOpened = await Globals.Now();
                currentOrderSummary.col_Status = Globals.k_int_status_sent;
            }
            currentOrderSummary.bFilterTableNumber = true;
            currentOrderSummary.bFilterSubtotal = true;
            currentOrderSummary.bFilterTimeSent = true;
            currentOrderSummary.bFilterCarryOut = true;
            // Ensure only numbers are entered
            try
            {
                if (tbTable.Text.Trim().Length > 0)
                    currentOrderSummary.col_TableNumber = Convert.ToInt16(tbTable.Text.Trim());
                else
                    currentOrderSummary.col_TableNumber = 0;
            }
            catch (System.FormatException)
            {
                currentOrderSummary.col_TableNumber = 0;
            }
            tbTable.Text = currentOrderSummary.col_TableNumber.ToString();
            currentOrderSummary.col_Subtotal = decCurrentSubtotal;
            Globals.OrderDetailRecords = new ObservableCollection<ServiceReferenceOpenRPOS.OrderDetail>();
            Globals.OrderOptionRecords = new ObservableCollection<ServiceReferenceOpenRPOS.OrderOption>();
            int iOrderDetailID = 0;
            Globals.OrderCheckRecords = await Globals.client.GetOrderCheckObjectsAsync(Globals.token, "OrderSummaryID=" + currentOrderSummary.col_ID.ToString() + " ORDER BY SeatNumber");
            AddSeatNumber(); //update list to validate seat number before saving in order detail table.
            odl = new ObservableCollection<OrderData>();
            // Traverse the list of order items and send those to the database
            foreach (OrderData orderData in lvCurrentOrder.Items)
            {
                odl.Add(orderData);
                if (orderData.Parent == null && (orderData.MenuItemID > 0 || orderData.OpenItemID > 0))
                {
                    // Add a new order detail item
                    ServiceReferenceOpenRPOS.OrderDetail orderDetail = new ServiceReferenceOpenRPOS.OrderDetail();
                    orderDetail.bFilterOrderSummaryID = true;
                    orderDetail.bFilterMenuItemID = true;
                    orderDetail.bFilterPrice = true;
                    orderDetail.bFilterSeatNumber = true;
                    orderDetail.bFilterDiscountID = true;
                    orderDetail.bFilterSent = true;
                    orderDetail.bFilterOpenItemID = true;
                    orderDetail.bFilterSplitItemID = true;
                    orderDetail.col_SplitItemID = orderData.SplitItemID;
                    orderDetail.col_OpenItemID = orderData.OpenItemID;
                    orderDetail.col_Sent = orderData.Sent;
                    orderDetail.col_OrderSummaryID = currentOrderSummary.col_ID;
                    orderDetail.col_MenuItemID = orderData.MenuItemID;
                    orderDetail.col_Price = orderData.Price;
                    orderDetail.col_ID = iOrderDetailID++;

                    if (orderData.Sent == false) //check and assign seat number of open check, if any check is closed in order (means payment started)
                    {
                        if (Globals.OrderCheckRecords.Count > 0)
                        {
                            for (int i = 0; i < lstSeatNumber.Count; i++)
                            {
                                int count = 0;
                                for (int j = 0; j < Globals.OrderCheckRecords.Count; j++)
                                {
                                    if (lstSeatNumber[i] == Globals.OrderCheckRecords[j].col_SeatNumber) count++;
                                }
                                if (count == 0)
                                {
                                    orderDetail.col_SeatNumber = (byte)lstSeatNumber[i];
                                    orderData.SeatNumber = (byte)lstSeatNumber[i];
                                    break;
                                }
                            }
                        }
                        else
                        {
                            orderDetail.col_SeatNumber = (byte)orderData.SeatNumber; orderData.SeatNumber = (byte)orderData.SeatNumber;
                        }
                    }
                    else // otherwise let's keep adding in first seat
                    { 
                        if (isSplit == false && Globals.OrderCheckRecords.Count == 0) orderData.SeatNumber = 0;
                        orderDetail.col_SeatNumber = (byte)orderData.SeatNumber; orderData.SeatNumber = (byte)orderData.SeatNumber;
                    }

                    orderDetail.col_DiscountID = orderData.DiscountID;
                    Globals.OrderDetailRecords.Add(orderDetail);
                    // Check for options
                    if (orderData.Options != null)
                        foreach (OrderData odOption in orderData.Options)
                        {
                            ServiceReferenceOpenRPOS.OrderOption orderOption = new ServiceReferenceOpenRPOS.OrderOption();
                            orderOption.bFilterMenuItemID = true;
                            orderOption.bFilterOrderDetailID = true;
                            orderOption.bFilterExclusive = true;
                            orderOption.bFilterExclude = true;
                            orderOption.bFilterPrice = true;
                            orderOption.bFilterDiscountID = true;
                            orderOption.col_Exclusive = odOption.Exclusive;
                            orderOption.col_Exclude = odOption.Exclude;
                            orderOption.col_MenuItemID = odOption.MenuItemID;
                            orderOption.col_OrderDetailID = orderDetail.col_ID;
                            orderOption.col_Price = (odOption.Exclude ? 0 : odOption.Price);
                            orderOption.col_DiscountID = odOption.DiscountID;
                            Globals.OrderOptionRecords.Add(orderOption);
                        }
                }
            }
            try
            {
                currentOrderSummary.bFilterSplit = true;
                if (isSplit == false && Globals.OrderCheckRecords.Count == 0) currentOrderSummary.col_Split = 1;
                else if (currentOrderSummary.col_Split > 1)
                {
                    int SplitCount = Globals.OrderDetailRecords.Select(a => a.col_SeatNumber).Distinct().Count();
                    currentOrderSummary.col_Split = Convert.ToByte(SplitCount);
                }
                currentOrderSummary.col_TimeSent = await Globals.Now();
                int iOrderSummaryID = 0;
                if (lvCurrentOrder.Items.Count > 0)
                {
                    iOrderSummaryID = await Globals.client.SendOrderAsync(Globals.token, currentOrderSummary, Globals.OrderDetailRecords, Globals.OrderOptionRecords);
                }
                lvCurrentOrder.ItemsSource = null;
                lvCurrentOrder.ItemsSource = odl;
                // Flag record as being sent locally
                foreach (OrderData orderData in lvCurrentOrder.Items)
                    orderData.Sent = true;
                if (currentOrderSummary.col_ID == 0) currentOrderSummary.col_ID = iOrderSummaryID;

                // Update Table to mark as Occupied
                ReleaseOccupiedTable(iCurrentTableNumber); //if occupied table is changed for selected order, then release old table.
                UpdateTableSepcification(currentOrderSummary.col_TableNumber, true);

                if (bPrint)
                {
                    // Update the print queue to print the order
                    ServiceReferenceOpenRPOS.PrintQueue pq = new ServiceReferenceOpenRPOS.PrintQueue();
                    pq.bFilterPrintOrder = true;
                    pq.col_PrintOrder = true;
                    pq.bFilterOrderSummaryID = true;
                    pq.col_OrderSummaryID = currentOrderSummary.col_ID;
                    pq.bFilterPrinted = true;
                    pq.col_Printed = false;
                    pq.bFilterPrintRoute = true;
                    var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
                    Object value = localSettings.Values[Globals.k_str_settings_order_print_route];
                    try
                    {
                        pq.col_PrintRoute = Convert.ToByte(value);
                    }
                    catch (Exception ex)
                    {
                        System.Diagnostics.Debug.WriteLine(ex.Message);
                    }
                    try
                    {
                        await Globals.client.AddPrintQueueObjectAsync(Globals.token, pq);
                    }
                    catch (Exception ex)
                    {
                        System.Diagnostics.Debug.WriteLine(ex.Message);
                    }
                }
            }
            catch (Exception ex)
            {
                // Determine if a network error occurred
                System.Diagnostics.Debug.WriteLine(ex.Message);
                Globals.strExceptionMessage = "sendOrder Exception: " + ex.Message;
                promptNetworkErrorOnSend();
            }
            finally
            {
                // Close the wait page...
                dialogPopup.IsOpen = false;
                isSplit = false;
            }
            return true;
        }


        private void AddSeatNumber()
        {
            lstSeatNumber.Clear();
            foreach (OrderData orderData in lvCurrentOrder.Items)
            {
                lstSeatNumber.Add(orderData.SeatNumber);
            }
            lstSeatNumber.Sort();
        }


        private async void UpdateTableSepcification(int tblNumber, bool isOccupied)
        {
            if (tblNumber <= 0) return; // There is nothing we need to do, in-case there is no valid table.
            try
            {
                Globals.TableSpecificationRecords = await Globals.client.GetTableSpecificationObjectsAsync(Globals.token, "1=1");

                ServiceReferenceOpenRPOS.TableSpecification tbl = Globals.TableSpecificationRecords.Where(tb => tb.col_TableNumber == tblNumber).FirstOrDefault();
                tbl.bFilterOccupied = true;
                tbl.col_Occupied = isOccupied;
                await Globals.client.UpdateTableSpecificationObjectAsync(Globals.token, tbl);
            }
            catch { }
            finally
            {
                if (isOccupied) iCurrentTableNumber = tblNumber;
                else iCurrentTableNumber = 0;
            }
        }


        private async void ReleaseOccupiedTable(int tblNumber)
        {
            if (tblNumber <= 0) return; //There is nothing needs to do, in-case there is no valid table.
            Globals.TableSpecificationRecords = await Globals.client.GetTableSpecificationObjectsAsync(Globals.token, "1=1");

            int countOrders = 0;
            try
            {
                //check if table is not associated with any open (non-closed) order, marked as available
                countOrders = Globals.OrderSummaryRecords.Where(os => os.col_TableNumber == tblNumber && os.col_Status != Globals.k_int_status_closed).Count();
            }
            catch { }
            if (countOrders <= 0)
            {
                UpdateTableSepcification(tblNumber, false);
            }
        }

        private async Task<Boolean> closeCurrentOrder()
        {
            // Disable the "close" button
            btnClose.IsEnabled = false;
            // Disable the "split" button
            btnSplit.IsEnabled = false;
            // Disable the "new" button
            btnNew.IsEnabled = false;
            // Close the check
            currentOrderSummary.bFilterTableNumber = true;
            currentOrderSummary.bFilterStatus = true;
            currentOrderSummary.bFilterSubtotal = true;
            currentOrderSummary.bFilterTimeClosed = true;
            currentOrderSummary.col_Subtotal = decCurrentSubtotal;
            currentOrderSummary.col_Status = Globals.k_int_status_closed;
            currentOrderSummary.col_TimeClosed = await Globals.Now();
            // Ensure only numbers are entered
            try
            {
                if (tbTable.Text.Trim().Length > 0)
                    currentOrderSummary.col_TableNumber = Convert.ToInt16(tbTable.Text.Trim());
                else
                    currentOrderSummary.col_TableNumber = 0;
            }
            catch (System.FormatException)
            {
                currentOrderSummary.col_TableNumber = 0;
            }
            tbTable.Text = currentOrderSummary.col_TableNumber.ToString();
            try
            {
                await Globals.client.UpdateOrderSummaryObjectAsync(Globals.token, currentOrderSummary);
                lvCurrentOrder.ItemsSource = null;
                odl.Clear();
                currentOrderSummary = new ServiceReferenceOpenRPOS.OrderSummary();
                recalculateTotal();
                await getOpenOrders();
                tbTable.Text = "0";
                if (isMenuGroup == false)
                {
                    OnNavButtonClick(grdNav.Children[0], null);
                }
                cmbOpenOrders.SelectedIndex = -1;
            }
            catch (Exception ex)
            {
                // Determine if a network error occurred
                System.Diagnostics.Debug.WriteLine(ex.Message);
                Globals.strExceptionMessage = "closeCurrentOrder Exception: " + ex.Message;
                promptNetworkErrorOnClose();
            }

            ReleaseOccupiedTable(iCurrentTableNumber); //Release Occupied table once order is closed.

            return true;
        }


        public async Task<Boolean> getOpenOrders()
        {
            try
            {
                // Return any non-closed orders
                string filter = "status!=" + Globals.k_int_status_closed.ToString() + " and LoginID>0";
                // Only Managers have the ability to view/edit other checks...
                if (!Globals.currentLogin.col_Manager)
                    filter += " and (LoginID=" + Globals.currentLogin.col_ID.ToString() + " or CarryOut=1)";
                Globals.OrderSummaryRecords = await Globals.client.GetOrderSummaryObjectsAsync(Globals.token, filter);
                // Add open orders to the combo box
                cmbOpenOrders.Items.Clear();
                orderSummaryIDList.Clear();
                foreach (ServiceReferenceOpenRPOS.OrderSummary os in Globals.OrderSummaryRecords)
                {
                    string strComboBoxItemText = "";
                    if (os.col_CarryOut)
                    {
                        strComboBoxItemText = "Carry Out - " + os.col_CustomerName;
                    }
                    else
                    {
                        strComboBoxItemText = Globals.LoginRecords.Where(x => x.col_ID == os.col_LoginID).First().col_DisplayName;
                        strComboBoxItemText += " - Table " + os.col_TableNumber.ToString() + ", # " + (os.col_ID % 100).ToString();
                    }
                    cmbOpenOrders.Items.Add(strComboBoxItemText);
                    orderSummaryIDList.Add(os.col_ID);
                }
                cmbOpenOrders.SelectedIndex = orderSummaryIDList.IndexOf(currentOrderSummary.col_ID);
            }
            catch (Exception ex)
            {
                // Determine if a network error occurred
                System.Diagnostics.Debug.WriteLine(ex.Message);
                Globals.strExceptionMessage = "getOpenOrders Exception: " + ex.Message;
                promptNetworkErrorOnGetOpenOrders();
            }
            return true;
        }


        private void btnDelete_Click(object sender, RoutedEventArgs e)
        {
            // Remove selected items from the list            
            orderDataList.Clear();
            foreach (OrderData od in lvCurrentOrder.SelectedItems)
            {
                if (!od.Exclusive)
                    if (lvCurrentOrder.SelectedItems.Contains(od))
                        orderDataList.Add(od);
            }
            lvCurrentOrder.ItemsSource = null;
            foreach (OrderData od in orderDataList)
            {
                // Only allow managers to remove sent items...
                if (Globals.currentLogin.col_Manager || (!od.Sent))
                {
                    if (od.Options != null)
                        foreach (OrderData odOption in od.Options)
                        {
                            // Remove the option from the list
                            odl.Remove(odOption);
                            // Deduct price from order subtotal
                            currentOrderSummary.col_Subtotal -= odOption.Price;
                        }
                    // Don't remove exclusive options...
                    if (!od.Exclusive)
                    {
                        // Clear the option from the parent, if one exists
                        if (od.Parent != null)
                            od.Parent.Options.Remove(od);
                        odl.Remove(od);
                        // Deduct price from order subtotal
                        currentOrderSummary.col_Subtotal -= od.Price;
                    }
                }
            }
            lvCurrentOrder.ItemsSource = odl;
            lvCurrentOrder.SelectedItems.Clear();
            recalculateTotal();
            btnSend.IsEnabled = true;
        }

        private void setTableNumber(int iAddValue)
        {
            int iCurrentTable;
            try
            {
                if (tbTable.Text.Trim().Length > 0)
                    iCurrentTable = Convert.ToInt16(tbTable.Text.Trim());
                else
                    iCurrentTable = 0;
            }
            catch (System.FormatException)
            {
                iCurrentTable = 0;
            }
            iCurrentTable += iAddValue;
            // Ensure the current table is in the range 0-100
            iCurrentTable = (iCurrentTable > Globals.k_int_max_tables ? Globals.k_int_max_tables : (iCurrentTable < 0 ? 0 : iCurrentTable));
            tbTable.Text = iCurrentTable.ToString();
        }

        private void btnTableUp_Click(object sender, RoutedEventArgs e)
        {
            // Set the current table number to the next table number
            setTableNumber(1);
        }


        private void btnTableDown_Click(object sender, RoutedEventArgs e)
        {
            // Set the current table number to the previous table number
            setTableNumber(-1);
        }


        private async void btnSend_Click(object sender, RoutedEventArgs e)
        {
            await sendOrder();
        }


        private async void Page_Loaded(object sender, RoutedEventArgs e)
        {
            await getOpenOrders();
        }


        private async Task<Decimal> updateDiscount(int iDiscountID, decimal dPreDiscountAmount, string strPad = "", int SeatNumber = 0)
        {
            decimal dDiscountDollarAmt = 0;
            ServiceReferenceOpenRPOS.Discount discountObject;
            if (Globals.DiscountRecords.Where(x => x.col_ID == iDiscountID).Count() == 0)
            {
                ObservableCollection<ServiceReferenceOpenRPOS.Discount> DiscountRecords = await Globals.client.GetDiscountObjectsAsync(Globals.token, "ID=" + iDiscountID.ToString());
                discountObject = DiscountRecords.First();
                Globals.DiscountRecords.Add(discountObject);
            }
            else
                discountObject = Globals.DiscountRecords.Where(x => x.col_ID == iDiscountID).First();
            // Only show non-zero discounts
            if (discountObject.col_Amount != 0)
            {
                OrderData orderDiscountData = new OrderData();
                orderDiscountData.Discount = true;
                orderDiscountData.DiscountID = discountObject.col_ID;
                if (discountObject.col_IsPercent)
                {
                    dDiscountDollarAmt = Math.Round((-1 * (discountObject.col_Amount / 100) * dPreDiscountAmount), 2);
                    orderDiscountData.Price = dDiscountDollarAmt;
                    orderDiscountData.DisplayPrice = dDiscountDollarAmt.ToString("N");
                    orderDiscountData.MenuItemName = strPad + "*** Discount - " + discountObject.col_Amount.ToString("N") + "%";
                }
                else
                {
                    dDiscountDollarAmt = (-1 * discountObject.col_Amount);
                    orderDiscountData.Price = dDiscountDollarAmt;
                    orderDiscountData.DisplayPrice = dDiscountDollarAmt.ToString("N");
                    orderDiscountData.MenuItemName = strPad + "*** Discount ";
                }
                orderDiscountData.SeatNumber = SeatNumber;
                orderDiscountData.FontColor = "Red";
                addOrderItem(orderDiscountData);
            }
            return dDiscountDollarAmt;
        }


        private async Task<Boolean> loadSelectedOrder()
        {
            try
            {
                // Display the wait page...
                WaitPage waitPage = new WaitPage();
                waitPage.Width = Windows.UI.Xaml.Window.Current.Bounds.Width;
                waitPage.Height = Windows.UI.Xaml.Window.Current.Bounds.Height;
                dialogPopup = new Popup();
                dialogPopup.Child = waitPage;
                dialogPopup.IsOpen = true;
                // Clear out the current order information
                lvCurrentOrder.ItemsSource = null;
                odl.Clear();
                // Initialize the running total...
                decCurrentSubtotal = 0;
                // Get the selected order
                if (cmbOpenOrders.SelectedIndex >= 0)
                    currentOrderSummary = Globals.OrderSummaryRecords.Where(x => x.col_ID == orderSummaryIDList[cmbOpenOrders.SelectedIndex]).First();
                // set Existing Table Number of selected order
                iCurrentTableNumber = currentOrderSummary.col_TableNumber;
                tbTable.Text = currentOrderSummary.col_TableNumber.ToString();
                currentOrderSummary.bFilterTableNumber = true;
                await Globals.client.UpdateOrderSummaryObjectAsync(Globals.token, currentOrderSummary);
                Globals.OrderDetailRecords = await Globals.client.GetOrderDetailObjectsAsync(Globals.token, "OrderSummaryID=" + currentOrderSummary.col_ID.ToString() + " order by ID");

                if (Globals.OrderDetailRecords.Count() > 0)
                {
                    string strOrderDetailIDs = "(";
                    foreach (ServiceReferenceOpenRPOS.OrderDetail od in Globals.OrderDetailRecords)
                    {
                        strOrderDetailIDs += od.col_ID.ToString() + ",";
                    }
                    strOrderDetailIDs = strOrderDetailIDs.Substring(0, strOrderDetailIDs.Length - 1) + ")";
                    Globals.OrderOptionRecords = await Globals.client.GetOrderOptionObjectsAsync(Globals.token, "OrderDetailID in " + strOrderDetailIDs + " order by ID");
                    // Add item to order
                    foreach (ServiceReferenceOpenRPOS.OrderDetail od in Globals.OrderDetailRecords)
                    {
                        // Add the order item
                        OrderData orderData = new OrderData();
                        bool bPizza = false;
                        if (od.col_MenuItemID > 0)
                        {
                            ServiceReferenceOpenRPOS.MenuItem mi = Globals.MenuItemRecords.Where(x => x.col_ID == od.col_MenuItemID).First();
                            orderData.MenuItemID = mi.col_ID;
                            orderData.MenuItemName = mi.col_FullName;
                            bPizza = mi.col_Pizza;
                        }
                        else
                        {
                            Globals.OpenItemRecords = await Globals.client.GetOpenItemObjectsAsync(Globals.token, "ID=" + od.col_OpenItemID);
                            ServiceReferenceOpenRPOS.OpenItem oi = Globals.OpenItemRecords.First();
                            orderData.MenuItemID = 0;
                            orderData.MenuItemName = oi.col_Name;
                            orderData.OpenItemID = oi.col_ID;
                            orderData.Price = oi.col_Price;
                            orderData.DisplayPrice = oi.col_Price.ToString("N");
                            bPizza = false;
                        }
                        orderData.SplitItemID = od.col_SplitItemID;
                        if (orderData.SplitItemID > 0)
                        {
                            // Load split item information
                            Globals.SplitItemRecords = await Globals.client.GetSplitItemObjectsAsync(Globals.token, "ID=" + orderData.SplitItemID.ToString());
                            if (Globals.SplitItemRecords.Count() > 0)
                            {
                                ServiceReferenceOpenRPOS.SplitItem si = Globals.SplitItemRecords.First();
                                orderData.MenuItemName = "1/" + si.col_Split.ToString() + " " + orderData.MenuItemName;
                            }
                        }
                        orderData.DisplayPrice = od.col_Price.ToString("N");
                        orderData.Price = od.col_Price;
                        orderData.DiscountID = od.col_DiscountID;
                        orderData.Discount = (od.col_DiscountID > 0);
                        orderData.SeatNumber = od.col_SeatNumber;
                        orderData.Sent = od.col_Sent;
                        decCurrentSubtotal += orderData.Price;
                        addOrderItem(orderData, false);
                        // Check for discount...
                        if (orderData.DiscountID != 0)
                        {
                            decimal dCurrentDiscountAmount = orderData.Price;
                            foreach (ServiceReferenceOpenRPOS.OrderOption oo in Globals.OrderOptionRecords.Where(x => x.col_OrderDetailID == od.col_ID))
                                dCurrentDiscountAmount += oo.col_Price;
                            // Be sure to include options in the discount
                            decCurrentSubtotal += await updateDiscount(orderData.DiscountID, dCurrentDiscountAmount, " ", orderData.SeatNumber);
                        }
                        // Add options...
                        if (Globals.OrderOptionRecords.Where(x => x.col_OrderDetailID == od.col_ID).Count() > 0)
                        {
                            orderData.Options = new List<OrderData>();
                            foreach (ServiceReferenceOpenRPOS.OrderOption oo in Globals.OrderOptionRecords.Where(x => x.col_OrderDetailID == od.col_ID))
                            {
                                OrderData orderOptionData = new OrderData();
                                ServiceReferenceOpenRPOS.MenuItem miOption = Globals.MenuItemRecords.Where(x => x.col_ID == oo.col_MenuItemID).First();
                                orderOptionData.MenuItemID = miOption.col_ID;
                                orderOptionData.MenuItemName = "  " + (oo.col_Exclude ? "No " : (bPizza && (!miOption.col_Pizza) ? "Add " : "")) + miOption.col_FullName;
                                orderOptionData.DisplayPrice = (oo.col_Price > 0) ? oo.col_Price.ToString("N") : "";
                                orderOptionData.Price = oo.col_Price;
                                orderOptionData.Exclusive = oo.col_Exclusive;
                                orderOptionData.Exclude = oo.col_Exclude;
                                orderOptionData.SeatNumber = od.col_SeatNumber;
                                orderData.Options.Add(orderOptionData);
                                orderOptionData.Parent = orderData;
                                decCurrentSubtotal += orderOptionData.Price;
                                addOrderItem(orderOptionData, false);
                            }
                        }
                    }
                    // If the summary record is attached to a discount, display the discount
                    if (currentOrderSummary.col_DiscountID != 0)
                    {
                        await updateDiscount(currentOrderSummary.col_DiscountID, decCurrentSubtotal);
                    }
                }
                updateTotals();
            }
            catch (Exception ex)
            {
                // Determine if a network error occurred
                System.Diagnostics.Debug.WriteLine(ex.Message);
                Globals.strExceptionMessage = "loadSelectedOrder Exception: " + ex.Message;
                promptNetworkErrorOnOpenOrdersSelectionChanged();
            }
            finally
            {
                // Enable the "close" button
                btnClose.IsEnabled = true;
                // Enable the "new" button
                btnNew.IsEnabled = true;
                // Enable the "split" button
                btnSplit.IsEnabled = true;
                // Disable the "send" button
                btnSend.IsEnabled = false;
                // Remove the wait page...
                dialogPopup.IsOpen = false;
            }
            return true;
        }


        private async void updateTotals()
        {
            decimal dDiscount = 0, dSubtotal, dTax = 0, dTotal;

            // Ensure current subtotal is accurate
            currentOrderSummary.col_Subtotal = decCurrentSubtotal;

            // Determine if there's a discount...
            if (currentOrderSummary.col_DiscountID > 0)
            {
                Globals.DiscountRecords = await Globals.client.GetDiscountObjectsAsync(Globals.token, "ID=" + currentOrderSummary.col_DiscountID);
                if (Globals.DiscountRecords.Count > 0)
                {
                    OrderData discountOrderData = null;
                    lvCurrentOrder.ItemsSource = null;
                    // Remove the current discount from the current order data list
                    foreach (OrderData od in odl)
                        if (od.Discount && od.DiscountID == Globals.DiscountRecords[0].col_ID)
                            discountOrderData = od;
                    if (discountOrderData != null)
                    {
                        // remove old discount...
                        odl.Remove(discountOrderData);
                        // Re-compute the new discount...
                        if (Globals.DiscountRecords[0].col_IsPercent)
                            dDiscount = Math.Round((decimal)(currentOrderSummary.col_Subtotal * (Globals.DiscountRecords[0].col_Amount / 100)), 2);
                        else
                            dDiscount = Globals.DiscountRecords[0].col_Amount;
                        // Create a new discount and add it to the current order data list
                        discountOrderData.Price = dDiscount * -1;
                        discountOrderData.DisplayPrice = discountOrderData.Price.ToString("N");
                        odl.Add(discountOrderData);
                    }
                    lvCurrentOrder.ItemsSource = odl;
                    lvCurrentOrder.ScrollIntoView(discountOrderData);
                }
            }
            dSubtotal = currentOrderSummary.col_Subtotal - dDiscount;
            tblkSubtotal.Text = dSubtotal.ToString("N");
            if (!currentOrderSummary.col_TaxExempt)
                dTax = Math.Round((decimal)((double)dSubtotal * Globals.tax_rate), 2);
            tblkTax.Text = dTax.ToString("N");
            dTotal = dSubtotal + dTax;
            tblkTotal.Text = dTotal.ToString("N");
        }

        private async void cmbOpenOrders_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if ((cmbOpenOrders.SelectedIndex >= 0) && (cmbOpenOrders.SelectedIndex != orderSummaryIDList.IndexOf(currentOrderSummary.col_ID)))
            {
                // Send the check (if needed)
                if (btnSend.IsEnabled)
                    await sendOrder();
                await loadSelectedOrder();
            }
        }


        private void cmbOpenOrders_DropDownOpened(object sender, object e)
        {
            // Removed code to improve behavior in Windows 10...
            //await getOpenOrders();
        }

        private async Task<Boolean> closeOrder(object sender, RoutedEventArgs e)
        {
            // Get the order check records  
            Globals.OrderCheckRecords = new ObservableCollection<ServiceReferenceOpenRPOS.OrderCheck>();
            ObservableCollection<ServiceReferenceOpenRPOS.OrderCheck> tmpOrderCheckRecords = await Globals.client.GetOrderCheckObjectsAsync(Globals.token, "OrderSummaryID=" + currentOrderSummary.col_ID.ToString() + " ORDER BY SeatNumber");
            int tmpCount = 0;

            foreach (ServiceReferenceOpenRPOS.OrderCheck oc in Globals.OrderCheckRecords)
            {
                // set Sub total if we call close Order
                oc.col_Subtotal = 0;
            }

            // Ensure that the current summary record has at least 1 check associated with it
            if (currentOrderSummary.col_Split == 0 || currentOrderSummary.col_Split == 1)
            {
                currentOrderSummary.col_Split = 1;
                // Ensure all items are on the same seat...
                Globals.OrderDetailRecords = await Globals.client.GetOrderDetailObjectsAsync(Globals.token, "OrderSummaryID=" + currentOrderSummary.col_ID.ToString() + " order by ID");
                foreach (ServiceReferenceOpenRPOS.OrderDetail od in Globals.OrderDetailRecords)
                    if (od.col_SeatNumber != 0)
                    {
                        od.bFilterSeatNumber = true;
                        od.col_SeatNumber = 0;
                        await Globals.client.UpdateOrderDetailObjectAsync(Globals.token, od);
                    }
                // Check items in the listview...
                foreach (OrderData od in lvCurrentOrder.Items)
                    if (od.SeatNumber != 0)
                        od.SeatNumber = 0;
            }
            // Determine if order checks exist for this check.  If not, create 1 for every split
            while (Globals.OrderCheckRecords.Count < currentOrderSummary.col_Split)
            {
                ServiceReferenceOpenRPOS.OrderCheck oc = null;
                //validate if seatnumber is available in ordercheck
                try
                {
                    oc = tmpOrderCheckRecords.FirstOrDefault(oct => oct.col_SeatNumber.ToString().Equals(tmpCount.ToString()));
                }
                catch { }
                if (oc == null)
                {
                    // Create a new order check record
                    oc = new ServiceReferenceOpenRPOS.OrderCheck();
                    // Set the filters
                    oc.bFilterGratuity = true;
                    oc.bFilterOrderSummaryID = true;
                    oc.bFilterPaid = true;
                    oc.bFilterPaymentType = true;
                    oc.bFilterSeatNumber = true;
                    oc.bFilterSubtotal = true;
                    oc.bFilterTax = true;
                    // Set the order summary ID
                    oc.col_OrderSummaryID = currentOrderSummary.col_ID;
                }

                // Add this record to the collection
                Globals.OrderCheckRecords.Add(oc);
                tmpCount++;
            }

            // Remove any excess records, if they exist
            if (Globals.OrderCheckRecords.Count() > currentOrderSummary.col_Split)
            {
                int cnt = Globals.OrderCheckRecords.Count();
                for (int i = cnt; cnt > currentOrderSummary.col_Split; cnt--)
                {
                    // There's a constraint on the print queue - it may make sense to clear the print queue of corresponding records
                    Globals.OrderCheckRecords.RemoveAt(cnt - 1);
                }
            }

            // Display the payment selection dialog
            CloseOrder cod = new CloseOrder();
            cod.init();
            cod.bTaxExempt = currentOrderSummary.col_TaxExempt;
            cod.iSplitCount = currentOrderSummary.col_Split;
            cod.iTableNO = currentOrderSummary.col_TableNumber;
            cod.iOrderNO = currentOrderSummary.col_ID;
            cod.iOrderDiscount = currentOrderSummary.col_DiscountID;
            // Set the header text...
            cod.setHeaderText("Select check #" + iCurrentSplitSeatNumber.ToString() + " items");
            cod.addOrderDetailItem(lvCurrentOrder.Items);
            cod.addChecks(currentOrderSummary.col_Split);
            cod.Width = Windows.UI.Xaml.Window.Current.Bounds.Width;
            cod.Height = Windows.UI.Xaml.Window.Current.Bounds.Height;
            //cod.
            cod.CloseRequested += CloseOrder_CloseRequested;
            dialogPopup = new Popup();
            dialogPopup.Child = cod;
            dialogPopup.IsOpen = true;

            return true;
        }


        private async void btnClose_Click(object sender, RoutedEventArgs e)
        {
            await closeOrder(sender, e);
        }

        private async void CloseOrder_CloseRequested(object sender, EventArgs e)
        {
            CloseOrder ccd = (CloseOrder)sender;
            dialogPopup.IsOpen = false;

            if (e == null)//check if it is cancel 
            {
                return;
            }

            await closeCurrentOrder();
        }


        private void CloseCheckDialog_CloseRequested(object sender, EventArgs e)
        {
            // Close the dialog...
            dialogPopup.IsOpen = false;
            // Show a payment dialog, cash or credit
            CloseCheckDialog ccd = (CloseCheckDialog)sender;
            if (!ccd.bCanceled)
            {
                // Create a new popup
                dialogPopup = new Popup();
                if (ccd.bCash)
                {
                    // Show the cash payment dialog
                    CashPaymentDialog cpd = new CashPaymentDialog();
                    cpd.init(Globals.OrderCheckRecords[iCurrentSplitSeatNumber].col_Subtotal, Globals.OrderCheckRecords[iCurrentSplitSeatNumber].col_Tax);
                    cpd.Width = Windows.UI.Xaml.Window.Current.Bounds.Width;
                    cpd.Height = Windows.UI.Xaml.Window.Current.Bounds.Height;
                    cpd.CloseRequested += CashPaymentDialog_CloseRequested;
                    dialogPopup = new Popup();
                    dialogPopup.Child = cpd;
                    dialogPopup.IsOpen = true;
                }
                else
                {
                    // Show the credit payment dialog
                    CreditPaymentDialog cpd = new CreditPaymentDialog();
                    cpd.init(Globals.OrderCheckRecords[iCurrentSplitSeatNumber].col_Subtotal, Globals.OrderCheckRecords[iCurrentSplitSeatNumber].col_Tax);
                    cpd.Width = Windows.UI.Xaml.Window.Current.Bounds.Width;
                    cpd.Height = Windows.UI.Xaml.Window.Current.Bounds.Height;
                    cpd.CloseRequested += CreditPaymentDialog_CloseRequested;
                    dialogPopup.Child = cpd;
                }
                // Show the dialog...
                dialogPopup.IsOpen = true;
            }
        }

        private async Task<bool> ProcessNextPayment()
        {
            // Determine if another check needs to be closed...
            if ((currentOrderSummary.col_Split > 0) && (iCurrentSplitSeatNumber + 1 < currentOrderSummary.col_Split))
            {
                CloseCheckDialog ccd = new CloseCheckDialog();
                iCurrentSplitSeatNumber++;

                // Determine the subtotal for the check...
                if (currentOrderSummary.col_Split > 1)
                {
                    Globals.OrderCheckRecords[iCurrentSplitSeatNumber].col_Subtotal = 0;
                    foreach (OrderData od in lvCurrentOrder.Items)
                        if (od.SeatNumber == iCurrentSplitSeatNumber)
                            Globals.OrderCheckRecords[iCurrentSplitSeatNumber].col_Subtotal += od.Price;
                }
                else
                {
                    Globals.OrderCheckRecords[0].col_Subtotal = 0;
                    iCurrentSplitSeatNumber = 0;
                    // Check has not been split...
                    foreach (OrderData od in lvCurrentOrder.Items)
                        Globals.OrderCheckRecords[0].col_Subtotal += od.Price;
                }
                // Calculate tax...
                Globals.OrderCheckRecords[iCurrentSplitSeatNumber].col_Tax = Math.Round((decimal)((double)Globals.OrderCheckRecords[iCurrentSplitSeatNumber].col_Subtotal * Globals.tax_rate), 2);

                ccd.init(Globals.OrderCheckRecords[iCurrentSplitSeatNumber].col_Subtotal + Globals.OrderCheckRecords[iCurrentSplitSeatNumber].col_Tax);
                ccd.Width = Windows.UI.Xaml.Window.Current.Bounds.Width;
                ccd.Height = Windows.UI.Xaml.Window.Current.Bounds.Height;
                ccd.CloseRequested += CloseCheckDialog_CloseRequested;
                dialogPopup = new Popup();
                dialogPopup.Child = ccd;
                dialogPopup.IsOpen = true;
            }
            else
            {
                bool bAllPaid = true;
                // Determine if all associated checks have been paid
                foreach (ServiceReferenceOpenRPOS.OrderCheck oc in Globals.OrderCheckRecords)
                    bAllPaid &= oc.col_Paid;
                // Close the entire order if all checks have been paid...
                if (bAllPaid)
                    await closeCurrentOrder();
            }
            return true;
        }

        private async void CashPaymentDialog_CloseRequested(object sender, EventArgs e)
        {
            // Close the dialog...
            dialogPopup.IsOpen = false;
            // Show the wait dialog
            CashPaymentDialog cpd = (CashPaymentDialog)sender;
            // If the check has not been canceled, close it out...
            if (!cpd.bCanceled)
            {
                Globals.OrderCheckRecords[iCurrentSplitSeatNumber].col_Paid = true;
                Globals.OrderCheckRecords[iCurrentSplitSeatNumber].col_Gratuity = cpd.dGratuity;
                // Send the updated record...
                if (Globals.OrderCheckRecords[iCurrentSplitSeatNumber].col_ID == 0)
                    // Need to add a new record
                    await Globals.client.AddOrderCheckObjectAsync(Globals.token, Globals.OrderCheckRecords[iCurrentSplitSeatNumber]);
                else
                    // Update this record
                    await Globals.client.UpdateOrderCheckObjectAsync(Globals.token, Globals.OrderCheckRecords[iCurrentSplitSeatNumber]);
                // Open cash drawer
                btnOpenDrawer_Click(sender, null);
            }
            // Process the next payment...
            await ProcessNextPayment();
        }

        private async void CreditPaymentDialog_CloseRequested(object sender, EventArgs e)
        {
            // Close the dialog...
            dialogPopup.IsOpen = false;
            // Show the wait dialog
            CreditPaymentDialog cpd = (CreditPaymentDialog)sender;
            // If the check has not been canceled, close it out...
            if (!cpd.bCanceled)
            {
                Globals.OrderCheckRecords[iCurrentSplitSeatNumber].col_Paid = true;
                Globals.OrderCheckRecords[iCurrentSplitSeatNumber].col_Gratuity = cpd.dGratuity;
                // Send the updated record...
                if (Globals.OrderCheckRecords[iCurrentSplitSeatNumber].col_ID == 0)
                    // Need to add a new record
                    await Globals.client.AddOrderCheckObjectAsync(Globals.token, Globals.OrderCheckRecords[iCurrentSplitSeatNumber]);
                else
                    // Update this record
                    await Globals.client.UpdateOrderCheckObjectAsync(Globals.token, Globals.OrderCheckRecords[iCurrentSplitSeatNumber]);
            }
            // Process the next payment...
            await ProcessNextPayment();
        }

        private async void btnNew_Click(object sender, RoutedEventArgs e)
        {
            // Send the check (if needed)
            if (btnSend.IsEnabled)
                await sendOrder();
            // Disable the "close" button
            btnClose.IsEnabled = false;
            // Disable the "split" button
            btnSplit.IsEnabled = false;
            // Disable the "new" button
            btnNew.IsEnabled = false;
            // Clear out the current order information
            lvCurrentOrder.ItemsSource = null;
            odl.Clear();
            currentOrderSummary = new ServiceReferenceOpenRPOS.OrderSummary();
            recalculateTotal();
            await getOpenOrders();
            tbTable.Text = "0";
            if (isMenuGroup == false)
            {
                OnNavButtonClick(grdNav.Children[0], null);
            }
            cmbOpenOrders.SelectedIndex = -1;
            // Determine if table layout should be displayed initially...
            if (Globals.defaultTableView) btnFindTable_Click(this, null);
        }


        private async void cmbOpenOrders_DropDownClosed(object sender, object e)
        {
            await getOpenOrders();

            if (currentOrderSummary.col_ID > 0 && cmbOpenOrders.SelectedIndex < 0)
            {
                cmbOpenOrders.SelectedIndex = orderSummaryIDList.IndexOf(currentOrderSummary.col_ID);
            }
        }


        private void tbTable_TextChanged(object sender, TextChangedEventArgs e)
        {
            // Re-enable the send button
            if (string.IsNullOrEmpty(tbTable.Text) == false && tbTable.Text != "0") btnSend.IsEnabled = true;
        }


        private async void btnSplit_Click(object sender, RoutedEventArgs e)
        {

            // Get the order check records
            Globals.OrderCheckRecords = await Globals.client.GetOrderCheckObjectsAsync(Globals.token, "OrderSummaryID=" + currentOrderSummary.col_ID.ToString() + " ORDER BY SeatNumber");
            ServiceReferenceOpenRPOS.MenuItem mi;
            if (lvCurrentOrder.SelectedItems.Count() == 1)
            {
                OrderData od = (OrderData)lvCurrentOrder.SelectedItems.First();
                if (od.Parent == null)
                {
                    // Split the selected item
                    OrderData newOrderData = new OrderData();
                    // Retrieve the split item from the database
                    Globals.SplitItemRecords.Clear();
                    if (od.SplitItemID > 0)
                        Globals.SplitItemRecords = await Globals.client.GetSplitItemObjectsAsync(Globals.token, "ID=" + od.SplitItemID.ToString());
                    ServiceReferenceOpenRPOS.SplitItem si;
                    if (Globals.SplitItemRecords.Count() > 0)
                    {
                        // Set the appropriate order data items
                        si = Globals.SplitItemRecords.First();
                        si.col_Split++;
                        if (si.col_FullPrice == 0)
                        {
                            si.col_FullPrice = od.Price;
                            si.col_Split++;
                        }
                        // Update the database
                        si.bFilterFullPrice = true;
                        si.bFilterSplit = true;
                        await Globals.client.UpdateSplitItemObjectAsync(Globals.token, si);
                    }
                    else
                    {
                        si = new ServiceReferenceOpenRPOS.SplitItem();
                        si.col_Split = 2;
                        si.col_FullPrice = od.Price;
                        si.bFilterFullPrice = true;
                        si.bFilterSplit = true;
                        si.col_ID = await Globals.client.AddSplitItemObjectAsync(Globals.token, si);
                        od.SplitItemID = si.col_ID;
                    }

                    // Break out prices for the split item
                    decimal[] dSplitPrices = new decimal[si.col_Split];
                    decimal dTotal = si.col_FullPrice;
                    int div = si.col_Split, cnt = 0;
                    while (div > 0)
                    {
                        decimal amt = Math.Round(dTotal / div, 2);
                        dSplitPrices[cnt++] = amt;
                        dTotal -= amt;
                        div--;
                    }

                    // Determine how many options are associated with the split item
                    int iOptCount = 0, iOptSplitCount = 0;
                    foreach (OrderData orderData in lvCurrentOrder.Items)
                        if (orderData.Parent == od)
                            iOptCount++;
                    // Create an array to store the split price of each option
                    decimal[,] dSplitOptionPrices = new decimal[si.col_Split, iOptCount];
                    // Reset iOptCount
                    iOptCount = 0;

                    orderDataList.Clear();
                    foreach (OrderData orderData in lvCurrentOrder.Items)
                    {
                        if (orderData.Parent == od)
                        {
                            // Get the corresponding menu item
                            mi = Globals.MenuItemRecords.Where(x => x.col_ID == orderData.MenuItemID).First();
                            dTotal = mi.col_Price;
                            div = si.col_Split;
                            while (div > 0)
                            {
                                decimal amt = Math.Round(dTotal / div, 2);
                                dSplitOptionPrices[iOptSplitCount++, iOptCount] = amt;
                                dTotal -= amt;
                                div--;
                            }
                            iOptCount++;
                            iOptSplitCount = 0;
                        }
                        orderDataList.Add(orderData);
                    }

                    od.DisplayPrice = od.Price.ToString("N");
                    mi = Globals.MenuItemRecords.Where(x => x.col_ID == od.MenuItemID).First();
                    od.MenuItemName = "1/" + si.col_Split.ToString() + " " + mi.col_FullName;
                    // Update new order data information
                    newOrderData.DisplayPrice = newOrderData.Price.ToString("N");
                    newOrderData.Exclude = od.Exclude;
                    newOrderData.Exclusive = od.Exclusive;
                    newOrderData.MenuItemID = od.MenuItemID;
                    newOrderData.MenuItemName = od.MenuItemName;
                    newOrderData.OpenItemID = od.OpenItemID;
                    newOrderData.Options = od.Options;
                    newOrderData.Parent = null;
                    newOrderData.Portion = od.Portion;
                    newOrderData.SeatNumber = od.SeatNumber;
                    newOrderData.Sent = od.Sent;
                    newOrderData.SplitItemID = od.SplitItemID;

                    // Add this item...
                    orderDataList.Add(newOrderData);
                    // Add options...
                    foreach (OrderData orderData in lvCurrentOrder.Items)
                        if (orderData.Parent == od)
                        {
                            OrderData orderOption = new OrderData();
                            orderOption.Parent = newOrderData;
                            orderOption.MenuItemName = orderData.MenuItemName;
                            orderOption.MenuItemID = orderData.MenuItemID;
                            orderDataList.Add(orderOption);
                        }

                    // Scan the list for additional split items...
                    OrderData lastSplitOrderItem = null, prevSplitOrderItem = null;
                    int lastCnt = cnt;
                    iOptCount = 0;
                    foreach (OrderData orderData in orderDataList)
                    {
                        if (orderData.SplitItemID == si.col_ID)
                        {
                            lastSplitOrderItem = orderData;
                            if (prevSplitOrderItem == null)
                                prevSplitOrderItem = lastSplitOrderItem;
                            orderData.Price = dSplitPrices[--cnt];
                            orderData.DisplayPrice = orderData.Price.ToString("N");
                            orderData.MenuItemName = od.MenuItemName;
                        }
                        if ((orderData.Parent == lastSplitOrderItem) && (orderData.Parent != null))
                        {
                            if (lastSplitOrderItem != prevSplitOrderItem)
                            {
                                iOptSplitCount++;
                                iOptCount = 0;
                                cnt = lastCnt;
                                prevSplitOrderItem = lastSplitOrderItem;
                            }
                            // Update the price information for this option...
                            orderData.Price = dSplitOptionPrices[iOptSplitCount, iOptCount++];
                            orderData.DisplayPrice = orderData.Price.ToString("N");
                        }
                    }
                    odl = new ObservableCollection<OrderData>(); 
                    foreach (OrderData oldOrderData in orderDataList)
                        odl.Add(oldOrderData);
                    lvCurrentOrder.ItemsSource = odl;
                    recalculateTotal();
                    // Enable the "Send" button
                    btnSend.IsEnabled = true;
                }
            }
            else
            {
                // Go directly to the "Split Check" dialog...
                dialogPopup = new Popup();
                dialogPopup.IsOpen = false;

                currentOrderSummary.bFilterSplit = true;
                if (currentOrderSummary.col_Split < 1)
                {
                    currentOrderSummary.col_Split = 1;
                    foreach (OrderData orderData in lvCurrentOrder.Items)
                        orderData.SeatNumber = 0;
                }
                currentOrderSummary.bFilterSplitEvenly = true;
                currentOrderSummary.col_SplitEvenly = false;
                SplitCheckByMenuItems(currentOrderSummary.col_Split);
            }
        }

        private void SplitCheckDialog_CloseRequested(object sender, EventArgs e)
        {
            dialogPopup.IsOpen = false;
            SplitCheckDialog scd = (SplitCheckDialog)sender;
            if (!scd.bCanceled)
            {
                currentOrderSummary.bFilterSplit = true;
                currentOrderSummary.col_Split = (byte)scd.iSplitCount;
                currentOrderSummary.bFilterSplitEvenly = true;
                currentOrderSummary.col_SplitEvenly = scd.bSplitEvenly;
                // If the check is not split evenly, split it out by order items
                if (!scd.bSplitEvenly)
                {
                    // Initialize order detail split
                    foreach (OrderData od in lvCurrentOrder.Items)
                        od.SeatNumber = 0;
                    if (scd.iSplitCount > 1)
                    {
                        SplitCheckByMenuItems(scd.iSplitCount);
                    }
                }
            }
        }


        private async void SplitCheckByMenuItems(int SplitCount)
        {
            // Create a new dialog to allow selection of menu items for first check...
            SplitMenuItemsDialog smid = new SplitMenuItemsDialog();
            smid.Width = Windows.UI.Xaml.Window.Current.Bounds.Width;
            smid.Height = Windows.UI.Xaml.Window.Current.Bounds.Height;
            smid.CloseRequested += SplitMenuItemsDialog_CloseRequested;
            dialogPopup = new Popup();
            dialogPopup.Child = smid;
            dialogPopup.IsOpen = true;
            iCurrentSplitSeatNumber = 1;
            smid.iCurrentSeat = iCurrentSplitSeatNumber;
            smid.iOrderNO = currentOrderSummary.col_ID;
            smid.iTableNO = currentOrderSummary.col_TableNumber;
            // Set the header text...
            smid.setHeaderText("Select check #" + iCurrentSplitSeatNumber.ToString() + " items");

            // Add detail items to dialog
            foreach (OrderData od in lvCurrentOrder.Items)
            {
                // Ensure discounts stay attached to appropriate seat
                if (od.DiscountID == currentOrderSummary.col_DiscountID && od.Discount)
                {
                    ServiceReferenceOpenRPOS.Discount discountObject = null;
                    if (Globals.DiscountRecords.Where(x => x.col_ID == od.DiscountID).Count() == 0)
                    {
                        ObservableCollection<ServiceReferenceOpenRPOS.Discount> DiscountRecords = await Globals.client.GetDiscountObjectsAsync(Globals.token, "ID=" + od.DiscountID.ToString());
                        discountObject = DiscountRecords.First();
                        Globals.DiscountRecords.Add(discountObject);
                    }
                    else
                        discountObject = Globals.DiscountRecords.Where(x => x.col_ID == od.DiscountID).First();
                    // Add an entire check discount...
                    smid.discountEntireOrder(discountObject.col_IsPercent, (int)discountObject.col_Amount, od.DiscountID);
                }
                else
                    smid.addOrderDetailItem(od);
            }

            smid.iSplitCount = SplitCount;
            await smid.addChecks(SplitCount);
        }

        private async void SplitMenuItemsDialog_CloseRequested(object sender, EventArgs e)
        {
            dialogPopup.IsOpen = false;

            SplitMenuItemsDialog scMenuItemdialog = (SplitMenuItemsDialog)sender;
            if (scMenuItemdialog != null) currentOrderSummary.col_Split = Convert.ToByte(scMenuItemdialog.iSplitCount);
            isSplit = true;
            if (e == null)//check if it is cancel 
            {
                isSplit = false;
                return;
            }
            // else send the order to save split checks count and menu items with appropriate seat number            
            await sendOrder(true);
        }


        private void btnManager_Click(object sender, RoutedEventArgs e)
        {
            // Show the manager dialog...
            ManagerDialog md = new ManagerDialog();
            md.Width = Windows.UI.Xaml.Window.Current.Bounds.Width;
            md.Height = Windows.UI.Xaml.Window.Current.Bounds.Height;
            md.CloseRequested += ManagerDialog_CloseRequested;
            dialogPopup = new Popup();
            dialogPopup.Child = md;
            dialogPopup.IsOpen = true;
        }

        private async void ManagerDialog_CloseRequested(object sender, EventArgs e)
        {
            ManagerDialog md = (ManagerDialog)sender;
            dialogPopup.IsOpen = false;
            // Determine what option was selected...
            if (!md.bCanceled)
            {
                Page page = new Page();

                if (md.bClearPrintQueue)
                {
                    // Prompt the user before logging out
                    var messageDialog = new MessageDialog("Are you sure you want to clear the print queue?");
                    // Add commands and set their callbacks; both buttons use the same callback function instead of inline event handlers
                    IUICommand icmdYes = new UICommand("Yes");
                    IUICommand icmdNo = new UICommand("No");
                    messageDialog.Commands.Add(icmdYes);
                    messageDialog.Commands.Add(icmdNo);
                    // Show the message dialog
                    if (await messageDialog.ShowAsync() == icmdYes)
                    {
                        Globals.PrintQueueRecords = await Globals.client.GetPrintQueueObjectsAsync(Globals.token, "Printed=0");
                        foreach (ServiceReferenceOpenRPOS.PrintQueue pq in Globals.PrintQueueRecords)
                        {
                            pq.bFilterPrinted = true;
                            pq.col_Printed = true;
                            await Globals.client.UpdatePrintQueueObjectAsync(Globals.token, pq);
                        }
                        // Clear print queue and prompt user
                        var messageDialogCompleted = new MessageDialog("Print queue has been cleared.");
                        await messageDialogCompleted.ShowAsync();
                    }
                }
                else if (md.bReopenChecks)
                {
                    WaitPage waitPage = new WaitPage();
                    waitPage.Width = Windows.UI.Xaml.Window.Current.Bounds.Width;
                    waitPage.Height = Windows.UI.Xaml.Window.Current.Bounds.Height;
                    dialogPopup.Child = waitPage;
                    dialogPopup.IsOpen = true;
                    // Create a new "ReOpen Checks" dialog
                    ReOpenChecksDialog rcd = new ReOpenChecksDialog();
                    rcd.CloseRequested += ReOpenChecksDialog_CloseRequested;
                    await rcd.init();
                    page = rcd;
                    dialogPopup.IsOpen = false;
                }
                else if (md.bCloseChecks)
                {
                    // Prompt the user before logging out
                    var messageDialog = new MessageDialog("Are you sure you want to close all open checks?");
                    // Add commands and set their callbacks; both buttons use the same callback function instead of inline event handlers
                    IUICommand icmdYes = new UICommand("Yes");
                    IUICommand icmdNo = new UICommand("No");
                    messageDialog.Commands.Add(icmdYes);
                    messageDialog.Commands.Add(icmdNo);
                    // Show the message dialog
                    if (await messageDialog.ShowAsync() == icmdYes)
                    {
                        Globals.OrderSummaryRecords = await Globals.client.GetOrderSummaryObjectsAsync(Globals.token, "Status!=" + Globals.k_int_status_closed.ToString());
                        foreach (ServiceReferenceOpenRPOS.OrderSummary os in Globals.OrderSummaryRecords)
                        {
                            os.bFilterStatus = true;
                            os.col_Status = Globals.k_int_status_closed;
                            await Globals.client.UpdateOrderSummaryObjectAsync(Globals.token, os);
                        }
                        // Close checks and prompt user
                        var messageDialogCompleted = new MessageDialog("All open checks have been closed.");
                        await messageDialogCompleted.ShowAsync();
                    }
                }
                else if (md.bDiscount)
                {
                    // Create a new "Discount" dialog
                    DiscountDialog dd = new DiscountDialog();
                    dd.CloseRequested += DiscountDialog_CloseRequested;
                    page = dd;
                }
                else if (md.bEmployeeChecks)
                {
                    WaitPage waitPage = new WaitPage();
                    waitPage.Width = Windows.UI.Xaml.Window.Current.Bounds.Width;
                    waitPage.Height = Windows.UI.Xaml.Window.Current.Bounds.Height;
                    dialogPopup.Child = waitPage;
                    dialogPopup.IsOpen = true;
                    // Create a new "Employee Checks" dialog
                    EmployeeChecksDialog ecd = new EmployeeChecksDialog();
                    ecd.CloseRequested += EmployeeChecksDialog_CloseRequested;
                    await ecd.init();
                    page = ecd;
                    dialogPopup.IsOpen = false;
                }
                else if (md.bGiftCards)
                {
                    // Launch the "Gift Cards" screen...
                    WaitPage waitPage = new WaitPage();
                    waitPage.Width = Windows.UI.Xaml.Window.Current.Bounds.Width;
                    waitPage.Height = Windows.UI.Xaml.Window.Current.Bounds.Height;
                    dialogPopup.Child = waitPage;
                    dialogPopup.IsOpen = true;
                    // Create a new "Gift Card" dialog
                    GiftCardDialog gcd = new GiftCardDialog();
                    gcd.CloseRequested += GiftCardDialog_CloseRequested;
                    page = gcd;
                    dialogPopup.IsOpen = false;
                }
                else if (md.bRefund)
                {
                    WaitPage waitPage = new WaitPage();
                    waitPage.Width = Windows.UI.Xaml.Window.Current.Bounds.Width;
                    waitPage.Height = Windows.UI.Xaml.Window.Current.Bounds.Height;
                    dialogPopup.Child = waitPage;
                    dialogPopup.IsOpen = true;
                    // Create a new "Refund" dialog
                    RefundDialog rd = new RefundDialog();
                    await rd.init();
                    rd.CloseRequested += RefundDialog_CloseRequested;
                    page = rd;
                    dialogPopup.IsOpen = false;
                }
                else if (md.bSettings)
                {
                    // Create a new "Settings" dialog
                    SettingsDialog sd = new SettingsDialog();
                    sd.CloseRequested += SettingsDialog_CloseRequested;
                    sd.init();
                    page = sd;
                }
                else if (md.bShowSales)
                {
                    // Get sales total and display it
                    decimal dSubtotal = 0, dTax = 0, dTotal = 0;
                    // Retrieve order summary records for closed checks by selected user
                    DateTime dtNow = await Globals.Now();
                    string strFilter = "Status=" + Globals.k_int_status_closed.ToString() +
                        " and TimeOpened between '" + dtNow.Date.Date.ToString() + "' and '" +
                        dtNow.Date.Date.AddDays(1).ToString() + ("'");
                    Globals.OrderSummaryRecords = await Globals.client.GetOrderSummaryObjectsAsync(Globals.token, strFilter);
                    string strOrderSummaryIDs = "";
                    Globals.OrderCheckRecords.Clear();
                    if (Globals.OrderSummaryRecords.Count() > 0)
                    {
                        foreach (ServiceReferenceOpenRPOS.OrderSummary os in Globals.OrderSummaryRecords)
                            strOrderSummaryIDs += os.col_ID.ToString() + ",";
                        strOrderSummaryIDs = strOrderSummaryIDs.Substring(0, strOrderSummaryIDs.Length - 1);
                        Globals.OrderCheckRecords = await Globals.client.GetOrderCheckObjectsAsync(Globals.token,
                            "OrderSummaryID in (" + strOrderSummaryIDs + ") order by OrderSummaryID, ID");
                    }
                    foreach (ServiceReferenceOpenRPOS.OrderCheck oc in Globals.OrderCheckRecords)
                    {
                        dSubtotal += oc.col_Subtotal;
                        dTax += oc.col_Tax;
                        dTotal += oc.col_Subtotal + oc.col_Tax;
                    }
                    dTotal = dSubtotal + dTax;
                    var messageDialog = new MessageDialog("Subtotal: $" + dSubtotal.ToString("N") + ", Tax: $" + dTax.ToString("N") + ", Total Sales: $" + dTotal.ToString("N"));
                    await messageDialog.ShowAsync();
                }
                else if (md.bTaxExempt)
                {
                    // Prompt the user before logging out
                    var messageDialog = new MessageDialog("Is the current order tax exempt?");
                    // Add commands and set their callbacks; both buttons use the same callback function instead of inline event handlers
                    IUICommand icmdYes = new UICommand("Yes");
                    IUICommand icmdNo = new UICommand("No");
                    messageDialog.Commands.Add(icmdYes);
                    messageDialog.Commands.Add(icmdNo);
                    currentOrderSummary.bFilterTaxExempt = true;
                    // Show the message dialog
                    if (await messageDialog.ShowAsync() == icmdYes)
                        // Flag current order as tax exempt
                        currentOrderSummary.col_TaxExempt = true;
                    else
                        currentOrderSummary.col_TaxExempt = false;
                    // Update the totals...
                    updateTotals();
                }
                else if (md.bTipAdjust)
                {
                    WaitPage waitPage = new WaitPage();
                    waitPage.Width = Windows.UI.Xaml.Window.Current.Bounds.Width;
                    waitPage.Height = Windows.UI.Xaml.Window.Current.Bounds.Height;
                    dialogPopup.Child = waitPage;
                    dialogPopup.IsOpen = true;
                    // Create a new "Tip Adjustment" dialog
                    TipAdjustmentDialog tad = new TipAdjustmentDialog();
                    await tad.init();
                    tad.CloseRequested += TipAdjustmentDialog_CloseRequested;
                    page = tad;
                    dialogPopup.IsOpen = false;
                }
                else if (md.bVoid)
                {
                    WaitPage waitPage = new WaitPage();
                    waitPage.Width = Windows.UI.Xaml.Window.Current.Bounds.Width;
                    waitPage.Height = Windows.UI.Xaml.Window.Current.Bounds.Height;
                    dialogPopup.Child = waitPage;
                    dialogPopup.IsOpen = true;
                    // Create a new "Void" dialog
                    VoidDialog vd = new VoidDialog();
                    await vd.init();
                    vd.CloseRequested += VoidDialog_CloseRequested;
                    page = vd;
                    dialogPopup.IsOpen = false;
                }
                // Create a new dialog popup
                page.Width = Windows.UI.Xaml.Window.Current.Bounds.Width;
                page.Height = Windows.UI.Xaml.Window.Current.Bounds.Height;
                dialogPopup = new Popup();
                dialogPopup.Child = page;
                dialogPopup.IsOpen = true;
            }
        }

        private void EmployeeChecksDialog_CloseRequested(object sender, EventArgs e)
        {
            // Close the dialog...
            dialogPopup.IsOpen = false;
        }

        private void ReOpenChecksDialog_CloseRequested(object sender, EventArgs e)
        {
            // Close the dialog...
            dialogPopup.IsOpen = false;
        }

        private void SettingsDialog_CloseRequested(object sender, EventArgs e)
        {
            // Close the dialog...
            dialogPopup.IsOpen = false;
        }

        private async void VoidDialog_CloseRequested(object sender, EventArgs e)
        {
            bool bFlagCheck = true;
            // Close the dialog...
            dialogPopup.IsOpen = false;
            // Display wait cursor...
            WaitPage waitPage = new WaitPage();
            waitPage.Width = Windows.UI.Xaml.Window.Current.Bounds.Width;
            waitPage.Height = Windows.UI.Xaml.Window.Current.Bounds.Height;
            dialogPopup.Child = waitPage;
            dialogPopup.IsOpen = true;
            // Create a void for the current check...
            VoidDialog vd = (VoidDialog)sender;
            if (!vd.bCanceled)
            {
                if (vd.iCheckNumber > 0)
                {
                    ServiceReferenceOpenRPOS.Void voidRecord = new ServiceReferenceOpenRPOS.Void();
                    voidRecord.bFilterOrderCheckID = true;
                    voidRecord.col_OrderCheckID = vd.iCheckNumber;
                    voidRecord.bFilterLoginID = true;
                    voidRecord.bFilterReason = true;
                    voidRecord.col_Reason = vd.strReason;
                    voidRecord.col_LoginID = Globals.currentLogin.col_ID;
                    // Add the refund record
                    await Globals.client.AddVoidObjectAsync(Globals.token, voidRecord);
                    // Pull back check...
                    Globals.OrderCheckRecords = await Globals.client.GetOrderCheckObjectsAsync(Globals.token, "ID=" + vd.iCheckNumber.ToString());
                    if (Globals.OrderCheckRecords.Count() > 0) { 
                        // For integrated credit transactions, send a void to the provider...
                        if (Globals.OrderCheckRecords[0].col_PaymentType == 1)
                        {
                            if (Globals.processMercury)
                            {
                                // Pull back the corresponding Mercury transaction
                                Globals.MercuryRecords = await Globals.client.GetMercuryObjectsAsync(Globals.token, "OrderCheckID=" + vd.iCheckNumber.ToString());
                                if (Globals.MercuryRecords.Count() > 0)
                                {
                                    // Send a "Void" transaction for this record...
                                    ServiceReferenceMercury.PaymentRequest request = new ServiceReferenceMercury.PaymentRequest();
                                    request.AcqRefData = Globals.MercuryRecords[0].col_AcqRefData;
                                    request.AuthCode = Globals.MercuryRecords[0].col_AuthCode;
                                    request.InvoiceNo = vd.iCheckNumber;
                                    request.Memo = Globals.k_str_memo;
                                    request.OperatorID = Globals.currentLogin.col_UserName;
                                    request.LaneID = 0;
                                    request.RecordNo = Globals.MercuryRecords[0].col_RecordNumber;
                                    request.RefNo = request.InvoiceNo.ToString();
                                    request.Authorize = Globals.OrderCheckRecords[0].col_Subtotal + Globals.OrderCheckRecords[0].col_Tax + Globals.OrderCheckRecords[0].col_Gratuity;
                                    request.Purchase = Globals.OrderCheckRecords[0].col_Subtotal + Globals.OrderCheckRecords[0].col_Tax;
                                    request.Gratuity = Globals.OrderCheckRecords[0].col_Gratuity;
                                    ServiceReferenceMercury.PaymentResponse response = await Globals.mercuryClient.ProcessPostAuthAsync(request);                                    
                                    System.Diagnostics.Debug.WriteLine(response.CmdStatus);
                                }
                            }
                            else if (Globals.processUSAePay)
                            {
                                // Pull back the corresponding USA ePay transaction
                                Globals.USAePayRecords = await Globals.client.GetUSAePayObjectsAsync(Globals.token, "OrderCheckID=" + vd.iCheckNumber.ToString());
                                if (Globals.USAePayRecords.Count() > 0)
                                {
                                    // Send a "Void" transaction for this record...
                                    ServiceReferenceUSAePay.PaymentRequest request = new ServiceReferenceUSAePay.PaymentRequest();
                                    request.SourceKey = Globals.strUSAePaySourceKey;
                                    request.Pin = Globals.strUSAePayPin;
                                    request.RefNum = Globals.USAePayRecords[0].col_RefNum;
                                    ServiceReferenceUSAePay.PaymentResponse response = await Globals.usaepayClient.ProcessVoidAsync(request);
                                    System.Diagnostics.Debug.WriteLine(response.Result);
                                }
                            }
                            else if (Globals.processBlackline)
                            {
                                bFlagCheck = false;
                                // Send a void transaction...
                                string exMessage="";
                                try
                                {
                                    decimal in_amount = Globals.OrderCheckRecords[0].col_Subtotal + Globals.OrderCheckRecords[0].col_Tax + Globals.OrderCheckRecords[0].col_Gratuity;
                                    int in_invoice = vd.iCheckNumber;
                                    string requestUrl = Globals.strBlacklineUrl + "/runTransaction?command=void&key=" + Globals.strBlacklineKey + "&password=" + Globals.strBlacklinePassword + "&Amount=" + in_amount.ToString() + "&terminalID=" + Globals.strBlacklineTerminalID + "&refId=" + in_invoice.ToString();
                                    BlacklineJsonResponse jsonResponse;
                                    HttpWebRequest request = WebRequest.Create(requestUrl) as HttpWebRequest;
                                    HttpWebResponse response = await request.GetResponseAsync() as HttpWebResponse;
                                    System.Diagnostics.Debug.WriteLine(response.Headers.ToString());
                                    if (response.StatusCode != HttpStatusCode.OK)
                                        throw new Exception(String.Format(
                                        "Server error (HTTP {0}: {1}).",
                                        response.StatusCode,
                                        response.StatusDescription));
                                    DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(BlacklineJsonResponse));
                                    object objResponse = jsonSerializer.ReadObject(response.GetResponseStream());
                                    jsonResponse = objResponse as BlacklineJsonResponse;
                                    System.Diagnostics.Debug.WriteLine(jsonResponse.ResultCode);
                                    // If the void is not approved, do flag it as "void" the check...
                                    if (jsonResponse.ResultCode != "Approved")
                                    {
                                        // Display message for user...
                                        var messageDialog = new MessageDialog(jsonResponse.AuthCode + " " + jsonResponse.Message);
                                        await messageDialog.ShowAsync();                                        
                                        System.Diagnostics.Debug.WriteLine(jsonResponse.AuthCode);
                                    }
                                    else bFlagCheck = true;
                                }
                                catch (Exception ex)
                                {
                                    exMessage = ex.Message;
                                }
                                if (exMessage != "")
                                {
                                    // Display message for user...
                                    var messageDialog = new MessageDialog(exMessage);
                                    // Add command to close the dialog...
                                    messageDialog.Commands.Add(new UICommand("Close"));
                                    await messageDialog.ShowAsync(); 
                                    System.Diagnostics.Debug.WriteLine(exMessage);
                                }
                            }
                        }
                        if (bFlagCheck)
                        {
                            // Flag check as voided...
                            Globals.OrderCheckRecords[0].bFilterVoided = true;
                            Globals.OrderCheckRecords[0].col_Voided = true;
                            await Globals.client.UpdateOrderCheckObjectAsync(Globals.token, Globals.OrderCheckRecords[0]);
                        }
                    }
                }
            }
            // Close the wait cursor...
            dialogPopup.IsOpen = false;
        }
        private async void GiftCardDialog_CloseRequested(object sender, EventArgs e)
        {
            // Close the wait cursor...
            dialogPopup.IsOpen = false;
            GiftCardDialog gcd = (GiftCardDialog)sender;
            if (!gcd.bCanceled)
            {
                if (Globals.processBlackline)
                {
                    // Display the blackline dialog..
                    BlacklineDialog bd = new BlacklineDialog();
                    bd.Width = Windows.UI.Xaml.Window.Current.Bounds.Width;
                    bd.Height = Windows.UI.Xaml.Window.Current.Bounds.Height;
                    dialogPopup.Child = bd;
                    dialogPopup.IsOpen = true;
                    // Create a gift card record...
                    ServiceReferenceOpenRPOS.GiftCard gc = new ServiceReferenceOpenRPOS.GiftCard();
                    gc.bFilterDateTimeStamp = true;
                    gc.bFilterAmount = true;
                    gc.bFilterTransactionType = true;
                    gc.col_DateTimeStamp = await Globals.client.GetCurrentTimeAsync(Globals.token);
                    string exMessage = "";
                    try
                    {
                        string requestUrl = Globals.strBlacklineUrl;
                        if (gcd.bActivate)
                        {
                            gc.col_Amount = gcd.decActivateAmount;
                            gc.col_TransactionType = "GiftActivate";
                            gc.col_ID = await Globals.client.AddGiftCardObjectAsync(Globals.token, gc);
                            requestUrl += "/runTransaction?command=GiftActivate&key=" + Globals.strBlacklineKey + "&password=" + Globals.strBlacklinePassword + "&Amount=" + gc.col_Amount.ToString("N") + "&terminalID=" + Globals.strBlacklineTerminalID + "&refId=" + gc.col_ID.ToString();
                        }
                        if (gcd.bAddValue)
                        {
                            gc.col_Amount = gcd.decAddAmount;
                            gc.col_TransactionType = "GiftAddValue";
                            gc.col_ID = await Globals.client.AddGiftCardObjectAsync(Globals.token, gc);
                            requestUrl += "/runTransaction?command=GiftAddValue&key=" + Globals.strBlacklineKey + "&password=" + Globals.strBlacklinePassword + "&Amount=" + gc.col_Amount.ToString("N") + "&terminalID=" + Globals.strBlacklineTerminalID + "&refId=" + gc.col_ID.ToString();
                        }
                        if (gcd.bGetBalance)
                        {
                            gc.col_Amount = 0;
                            gc.col_TransactionType = "GiftBalance";
                            gc.col_ID = await Globals.client.AddGiftCardObjectAsync(Globals.token, gc);
                            requestUrl += "/runTransaction?command=GiftBalance&key=" + Globals.strBlacklineKey + "&password=" + Globals.strBlacklinePassword + "&Amount=" + gc.col_Amount.ToString("N") + "&terminalID=" + Globals.strBlacklineTerminalID + "&refId=" + gc.col_ID.ToString();
                        }
                        if (gcd.bRefund)
                        {
                            gc.col_Amount = gcd.decRefundAmount;
                            gc.col_TransactionType = "GiftRefund";
                            gc.col_ID = await Globals.client.AddGiftCardObjectAsync(Globals.token, gc);
                            requestUrl += "/runTransaction?command=GiftRefund&key=" + Globals.strBlacklineKey + "&password=" + Globals.strBlacklinePassword + "&Amount=" + gc.col_Amount.ToString("N") + "&terminalID=" + Globals.strBlacklineTerminalID + "&refId=" + gc.col_ID.ToString();
                        }
                        if (gcd.bSale)
                        {
                            gc.col_Amount = gcd.decSaleAmount;
                            gc.col_TransactionType = "GiftSale";
                            gc.col_ID = await Globals.client.AddGiftCardObjectAsync(Globals.token, gc);
                            requestUrl += "/runTransaction?command=GiftSale&key=" + Globals.strBlacklineKey + "&password=" + Globals.strBlacklinePassword + "&Amount=" + gc.col_Amount.ToString("N") + "&terminalID=" + Globals.strBlacklineTerminalID + "&refId=" + gc.col_ID.ToString();
                        }
                        BlacklineJsonResponse jsonResponse;
                        HttpWebRequest request = WebRequest.Create(requestUrl) as HttpWebRequest;
                        HttpWebResponse response = await request.GetResponseAsync() as HttpWebResponse;
                        System.Diagnostics.Debug.WriteLine(response.Headers.ToString());
                        if (response.StatusCode != HttpStatusCode.OK)
                            throw new Exception(String.Format(
                            "Server error (HTTP {0}: {1}).",
                            response.StatusCode,
                            response.StatusDescription));
                        DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(BlacklineJsonResponse));
                        object objResponse = jsonSerializer.ReadObject(response.GetResponseStream());
                        jsonResponse = objResponse as BlacklineJsonResponse;
                        System.Diagnostics.Debug.WriteLine(jsonResponse.ResultCode);
                        // Update the giftcard record
                        gc.bFilterAuthCode = true;
                        gc.bFilterMessage = true;
                        gc.bFilterResultCode = true;
                        gc.col_AuthCode = jsonResponse.AuthCode;
                        gc.col_Message = jsonResponse.Message;
                        gc.col_ResultCode = jsonResponse.Message;
                        if (gcd.bGetBalance)
                        {
                            gc.bFilterAmount = true;
                            gc.col_Amount = jsonResponse.GiftCardBalance;
                        }
                        await Globals.client.UpdateGiftCardObjectAsync(Globals.token, gc);
                    }
                    catch (Exception ex)
                    {
                        exMessage = ex.Message;
                    }
                    if (exMessage != "")
                    {
                        // Display message for user...
                        var messageDialog = new MessageDialog(exMessage);
                        await messageDialog.ShowAsync();
                        System.Diagnostics.Debug.WriteLine(exMessage);
                    }
                    // Close the dialog
                    dialogPopup.IsOpen = false;
                }
            }
        }
        private async void RefundDialog_CloseRequested(object sender, EventArgs e)
        {
            bool bRefundApproved = true;
            // Close the dialog...
            dialogPopup.IsOpen = false;
            // Create a refund for the current check...
            RefundDialog rd = (RefundDialog)sender;
            if (!rd.bCanceled)
            {
                if (rd.iCheckNumber > 0)
                {
                    ServiceReferenceOpenRPOS.Refund refund = new ServiceReferenceOpenRPOS.Refund();
                    refund.bFilterOrderCheckID = true;
                    refund.col_OrderCheckID = rd.iCheckNumber;
                    refund.bFilterAmount = true;
                    refund.bFilterLoginID = true;
                    refund.bFilterReason = true;
                    refund.col_Amount = rd.dRefundAmount;
                    refund.col_Reason = rd.strReason;
                    refund.col_LoginID = Globals.currentLogin.col_ID;
                    // For integrated credit transactions, send a void to the provider...
                    if (Globals.OrderCheckRecords[0].col_PaymentType == 1)
                    {
                        if (Globals.processBlackline)
                        {
                            // Display the blackline dialog..
                            BlacklineDialog bd = new BlacklineDialog();
                            bd.Width = Windows.UI.Xaml.Window.Current.Bounds.Width;
                            bd.Height = Windows.UI.Xaml.Window.Current.Bounds.Height;
                            dialogPopup.Child = bd;
                            dialogPopup.IsOpen = true;
                            bRefundApproved = false;
                            // Send a refund transaction...
                            string exMessage = "";
                            try
                            {
                                decimal in_amount = rd.dRefundAmount;
                                int in_invoice = rd.iCheckNumber;
                                string requestUrl = Globals.strBlacklineUrl + "/runTransaction?command=refund&key=" + Globals.strBlacklineKey + "&password=" + Globals.strBlacklinePassword + "&Amount=" + in_amount.ToString() + "&terminalID=" + Globals.strBlacklineTerminalID + "&refId=" + in_invoice.ToString();
                                BlacklineJsonResponse jsonResponse;
                                HttpWebRequest request = WebRequest.Create(requestUrl) as HttpWebRequest;
                                HttpWebResponse response = await request.GetResponseAsync() as HttpWebResponse;
                                System.Diagnostics.Debug.WriteLine(response.Headers.ToString());
                                if (response.StatusCode != HttpStatusCode.OK)
                                    throw new Exception(String.Format(
                                    "Server error (HTTP {0}: {1}).",
                                    response.StatusCode,
                                    response.StatusDescription));
                                DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(BlacklineJsonResponse));
                                object objResponse = jsonSerializer.ReadObject(response.GetResponseStream());
                                jsonResponse = objResponse as BlacklineJsonResponse;
                                System.Diagnostics.Debug.WriteLine(jsonResponse.ResultCode);
                                // If the adjustment is not approved, do not close the check...
                                if (jsonResponse.ResultCode != "Approved")
                                {
                                    // Display message for user...
                                    var messageDialog = new MessageDialog(jsonResponse.AuthCode + " " + jsonResponse.Message);
                                    await messageDialog.ShowAsync();
                                    System.Diagnostics.Debug.WriteLine(jsonResponse.AuthCode);
                                }
                                else bRefundApproved = true;
                            }
                            catch (Exception ex)
                            {
                                exMessage = ex.Message;
                            }
                            if (exMessage != "")
                            {
                                // Display message for user...
                                var messageDialog = new MessageDialog(exMessage);
                                await messageDialog.ShowAsync();
                                System.Diagnostics.Debug.WriteLine(exMessage);
                            }
                            // Close the dialog
                            dialogPopup.IsOpen = false;
                        }
                    }
                    if (bRefundApproved)
                        // Add the refund record
                        await Globals.client.AddRefundObjectAsync(Globals.token, refund);
                }
            }

        }

        private async void TipAdjustmentDialog_CloseRequested(object sender, EventArgs e)
        {
            // Close the dialog...
            dialogPopup.IsOpen = false;
            // Display wait cursor...
            WaitPage waitPage = new WaitPage();
            waitPage.Width = Windows.UI.Xaml.Window.Current.Bounds.Width;
            waitPage.Height = Windows.UI.Xaml.Window.Current.Bounds.Height;
            dialogPopup.Child = waitPage;
            dialogPopup.IsOpen = true;
            // Adjust the tip for the selected check
            TipAdjustmentDialog tad = (TipAdjustmentDialog)sender;
            if (!tad.bCanceled && Globals.OrderCheckRecords.Count > 0)
            {
                ServiceReferenceOpenRPOS.OrderCheck oc = Globals.OrderCheckRecords[tad.iSelectedIndex];
                oc.bFilterGratuity = true;
                oc.col_Gratuity = tad.dTip;

                if (Globals.processBlackline)
                {
                    // Perform a tip adjustment...
                    string exMessage = "";
                    try
                    {
                        decimal in_amount = oc.col_Subtotal + oc.col_Tax + oc.col_Gratuity;
                        int in_invoice = oc.col_ID;
                        string requestUrl = Globals.strBlacklineUrl + "/runTransaction?command=tipadjust&key=" + Globals.strBlacklineKey + "&password=" + Globals.strBlacklinePassword + "&Amount=" + in_amount.ToString() + "&terminalID=" + Globals.strBlacklineTerminalID + "&refId=" + in_invoice.ToString();
                        BlacklineJsonResponse jsonResponse;
                        HttpWebRequest request = WebRequest.Create(requestUrl) as HttpWebRequest;
                        HttpWebResponse response = await request.GetResponseAsync() as HttpWebResponse;
                        System.Diagnostics.Debug.WriteLine(response.Headers.ToString());
                        if (response.StatusCode != HttpStatusCode.OK)
                            throw new Exception(String.Format(
                            "Server error (HTTP {0}: {1}).",
                            response.StatusCode,
                            response.StatusDescription));
                        DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(BlacklineJsonResponse));
                        object objResponse = jsonSerializer.ReadObject(response.GetResponseStream());
                        jsonResponse = objResponse as BlacklineJsonResponse;
                        System.Diagnostics.Debug.WriteLine(jsonResponse.ResultCode);
                        // If the adjustment is not approved, do not close the check...
                        if (jsonResponse.ResultCode != "Approved")
                        {
                            // Display message for user...
                            var messageDialog = new MessageDialog(jsonResponse.AuthCode + " " + jsonResponse.Message);
                            await messageDialog.ShowAsync();
                            System.Diagnostics.Debug.WriteLine(jsonResponse.AuthCode);
                            // Don't close the check...
                            return;
                        }
                    }
                    catch (Exception ex)
                    {
                        exMessage = ex.Message;
                    }
                    if (exMessage != "")
                    {
                        // Display message for user...
                        var messageDialog = new MessageDialog(exMessage);
                        // Add command to close the dialog...
                        messageDialog.Commands.Add(new UICommand("Close"));
                        await messageDialog.ShowAsync();
                        System.Diagnostics.Debug.WriteLine(exMessage);
                        // Don't close the check...
                        return;
                    }
                }
                // Update the check with tip adjustment information...
                await Globals.client.UpdateOrderCheckObjectAsync(Globals.token, oc);
            }
            dialogPopup.IsOpen = false;
        }

        private async void DiscountDialog_CloseRequested(object sender, EventArgs e)
        {
            // Close the dialog...
            dialogPopup.IsOpen = false;
            // Display wait cursor...
            WaitPage waitPage = new WaitPage();
            waitPage.Width = Windows.UI.Xaml.Window.Current.Bounds.Width;
            waitPage.Height = Windows.UI.Xaml.Window.Current.Bounds.Height;
            Popup dp = new Popup();
            dp.Child = waitPage;
            dp.IsOpen = true;
            // Determine which discount was selected and the amount...
            DiscountDialog dd = (DiscountDialog)sender;
            // Determine whether or not the dialog was canceled 
            if (!dd.bCanceled)
            {
                // Create a new discount record
                ServiceReferenceOpenRPOS.Discount discountObject = new ServiceReferenceOpenRPOS.Discount();
                discountObject.bFilterAmount = true;
                discountObject.bFilterIsPercent = true;
                discountObject.bFilterLoginID = true;
                discountObject.col_Amount = dd.dAmount;
                discountObject.col_IsPercent = !dd.bDollarAmount;
                discountObject.col_LoginID = Globals.currentLogin.col_ID;
                discountObject.col_ID = await Globals.client.AddDiscountObjectAsync(Globals.token, discountObject);
                Globals.DiscountRecords.Add(discountObject);
                // Update the appropriate records
                if (dd.bEntireOrder)
                {
                    // Apply discount record to summary record
                    currentOrderSummary.bFilterDiscountID = true;
                    currentOrderSummary.col_DiscountID = discountObject.col_ID;
                    await Globals.client.UpdateOrderSummaryObjectAsync(Globals.token, currentOrderSummary);
                }
                else
                {
                    // Apply discount to selected records
                    foreach (OrderData od in lvCurrentOrder.SelectedItems)
                        od.DiscountID = discountObject.col_ID;
                    recalculateTotal();
                    // Re-send the order to update discount information...
                    await sendOrder(false);
                }
                // Send the order if it hasn't been sent yet...
                if (btnSend.IsEnabled) await sendOrder();
                // Update the display with the discount information
                await loadSelectedOrder();
            }
            dp.IsOpen = false;
        }


        private void btnSend_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            // Don't enable "Close" if "Send" is enabled - Force sending before closing
            if (btnSend.IsEnabled)
                btnClose.IsEnabled = false;
            else
                btnClose.IsEnabled = (lvCurrentOrder.Items.Count > 0);
        }


        private void btnStatus_Click(object sender, RoutedEventArgs e)
        {
            // Display the status of all orders
            StatusDialog sd = new StatusDialog();
            sd.Width = Windows.UI.Xaml.Window.Current.Bounds.Width;
            sd.Height = Windows.UI.Xaml.Window.Current.Bounds.Height;
            sd.CloseRequested += StatusDialog_CloseRequested;
            sd.init();
            dialogPopup = new Popup();
            dialogPopup.Child = sd;
            dialogPopup.IsOpen = true;
        }

        private void StatusDialog_CloseRequested(object sender, EventArgs e)
        {
            // Close the dialog...
            dialogPopup.IsOpen = false;
        }


        private void btnCarryOut_Click(object sender, RoutedEventArgs e)
        {
            // Present the carry out dialog
            CarryOutDialog cod = new CarryOutDialog();
            cod.Width = Windows.UI.Xaml.Window.Current.Bounds.Width;
            cod.Height = Windows.UI.Xaml.Window.Current.Bounds.Height;
            cod.CloseRequested += CarryOutDialog_CloseRequested;
            cod.init(currentOrderSummary);
            dialogPopup = new Popup();
            dialogPopup.Child = cod;
            dialogPopup.IsOpen = true;
        }

        private async void CarryOutDialog_CloseRequested(object sender, EventArgs e)
        {
            // Close the dialog...
            dialogPopup.IsOpen = false;
            // Update carry out data...
            CarryOutDialog cod = (CarryOutDialog)dialogPopup.Child;
            if (cod.bUpdated)
            {
                currentOrderSummary.col_CarryOut = cod.orderSummary.col_CarryOut;
                currentOrderSummary.col_CustomerName = cod.orderSummary.col_CustomerName;
                currentOrderSummary.col_CustomerPhone = cod.orderSummary.col_CustomerPhone;
                currentOrderSummary.bFilterCustomerName = true;
                currentOrderSummary.bFilterCustomerPhone = true;
                await sendOrder();
            }
        }


        private async void btnPrint_Click(object sender, RoutedEventArgs e)
        {
            // Send the order if it hasn't been sent...
            if (btnSend.IsEnabled)
                await sendOrder();

            if (currentOrderSummary.col_ID <= 0) return;

            Globals.OrderCheckRecords = await Globals.client.GetOrderCheckObjectsAsync(Globals.token, "OrderSummaryID=" + currentOrderSummary.col_ID.ToString());

            // Ensure that the current summary record has at least 1 check associated with it
            if (currentOrderSummary.col_Split <= 1)
            {
                currentOrderSummary.col_Split = 1;
                foreach (OrderData od in lvCurrentOrder.Items)
                    od.SeatNumber = 0;
            }
            // Determine if order checks exist for this check.  If not, create 1 for every split
            while (Globals.OrderCheckRecords.Count < currentOrderSummary.col_Split)
            {
                // Create a new order check record
                ServiceReferenceOpenRPOS.OrderCheck oc = new ServiceReferenceOpenRPOS.OrderCheck();
                // Set the filters
                oc.bFilterGratuity = true;
                oc.bFilterOrderSummaryID = true;
                oc.bFilterSeatNumber = true;
                oc.bFilterSubtotal = true;
                oc.bFilterTax = true;
                // Set the order summary ID
                oc.col_OrderSummaryID = currentOrderSummary.col_ID;
                oc.col_Subtotal = 0;
                // Update Tax Information
                oc.col_Gratuity = 0.00M;
                oc.col_Tax = Math.Round((decimal)((double)oc.col_Subtotal * Globals.tax_rate), 2);
                oc.col_SeatNumber = 0;
                // Add this record to the collection
                Globals.OrderCheckRecords.Add(oc);
                oc.col_ID = await Globals.client.AddOrderCheckObjectAsync(Globals.token, oc);
            }

            int curr_seat = 0;
            // Ensure subtotals are correct
            foreach (ServiceReferenceOpenRPOS.OrderCheck oc in Globals.OrderCheckRecords)
            {
                // Set the filters
                oc.bFilterGratuity = true;
                oc.bFilterOrderSummaryID = true;
                oc.bFilterSeatNumber = true;
                oc.bFilterSubtotal = true;
                oc.bFilterTax = true;
                // Set the order summary ID
                oc.col_OrderSummaryID = currentOrderSummary.col_ID;
                oc.col_Subtotal = 0;
                foreach (OrderData od in lvCurrentOrder.Items)
                {
                    if (od.MenuItemID > 0 || od.OpenItemID > 0)
                    {
                        if ((od.Parent == null) && (od.SeatNumber == curr_seat))
                        {
                            oc.col_Subtotal += od.Price;
                            foreach (OrderData odc in lvCurrentOrder.Items)
                            {
                                if (odc.Parent == od)
                                    oc.col_Subtotal += odc.Price;
                            }
                        }
                        // Check for discount...
                        if (od.DiscountID > 0)
                        {
                            Globals.DiscountRecords = await Globals.client.GetDiscountObjectsAsync(Globals.token, "ID=" + od.DiscountID);
                            if (Globals.DiscountRecords.Count > 0)
                            {
                                decimal dCurrentDiscount;
                                if (Globals.DiscountRecords[0].col_IsPercent)
                                {
                                    decimal dCurrentAmount = od.Price;
                                    // Be sure to include subitems as part of the discount total
                                    foreach (OrderData odi in lvCurrentOrder.Items)
                                        if (odi.Parent == od)
                                            dCurrentAmount += odi.Price;
                                    dCurrentDiscount = Math.Round((decimal)(dCurrentAmount * (Globals.DiscountRecords[0].col_Amount / 100)), 2);
                                }
                                else
                                    dCurrentDiscount = Globals.DiscountRecords[0].col_Amount;
                                oc.col_Subtotal -= dCurrentDiscount;
                            }
                        }
                    }
                }
                // Determine if there is a discount that should be applied to the entire check
                if (currentOrderSummary.col_DiscountID > 0)
                {
                    // Get the discount information
                    Globals.DiscountRecords = await Globals.client.GetDiscountObjectsAsync(Globals.token, "ID=" + currentOrderSummary.col_DiscountID);
                    if (Globals.DiscountRecords.Count > 0)
                    {
                        decimal dCurrentDiscount;
                        if (Globals.DiscountRecords[0].col_IsPercent)
                            dCurrentDiscount = Math.Round((decimal)(oc.col_Subtotal * (Globals.DiscountRecords[0].col_Amount / 100)), 2);
                        else
                            dCurrentDiscount = Globals.DiscountRecords[0].col_Amount;
                        oc.col_Subtotal -= dCurrentDiscount;
                    }
                }
                oc.col_Gratuity = 0.00M;
                oc.col_Tax = Math.Round((decimal)((double)oc.col_Subtotal * Globals.tax_rate), 2);
                oc.col_SeatNumber = (byte)curr_seat++;
                // Update the check...
                await Globals.client.UpdateOrderCheckObjectAsync(Globals.token, oc);
            }

            for (int cnt = 0; cnt < currentOrderSummary.col_Split; cnt++)
            {
                ServiceReferenceOpenRPOS.OrderCheck oc = Globals.OrderCheckRecords[cnt];
                // Update the print queue to print the order reciepts
                ServiceReferenceOpenRPOS.PrintQueue pq = new ServiceReferenceOpenRPOS.PrintQueue();
                pq.bFilterPrintOrder = true;
                pq.col_PrintOrder = false;
                pq.bFilterPrintReceipt = true;
                pq.col_PrintReceipt = true;
                pq.bFilterOrderCheckID = true;
                pq.col_OrderCheckID = oc.col_ID;
                pq.bFilterOrderSummaryID = true;
                pq.col_OrderSummaryID = currentOrderSummary.col_ID;
                pq.bFilterPrinted = true;
                pq.col_Printed = false;
                pq.bFilterPrintRoute = true;
                var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
                Object value = localSettings.Values[Globals.k_str_settings_receipt_print_route];
                try
                {
                    pq.col_PrintRoute = Convert.ToByte(value);
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine(ex.Message);
                }
                try
                {
                    await Globals.client.AddPrintQueueObjectAsync(Globals.token, pq);
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine(ex.Message);
                }

            }
        }

        private async void btnFindTable_Click(object sender, RoutedEventArgs e)
        {
            // Present the Table Selection dialog
            TablePicker tp = new TablePicker();
            tp.Width = Windows.UI.Xaml.Window.Current.Bounds.Width;
            tp.Height = Windows.UI.Xaml.Window.Current.Bounds.Height;
            tp.CloseRequested += TablePickerDialog_CloseRequested;
            await tp.init();
            dialogPopup = new Popup();
            dialogPopup.Child = tp;
            dialogPopup.IsOpen = true;
        }

        private void TablePickerDialog_CloseRequested(object sender, EventArgs e)
        {
            // Close the dialog...
            dialogPopup.IsOpen = false;
            // Update table number...
            TablePicker tp = (TablePicker)dialogPopup.Child;
            if (tp.bUpdated)
            {
                tbTable.Text = tp.tableNo;
                tbTable_TextChanged(tbTable, null);
                // Determine if the selected table is in the open order list...
                int idx = 0;
                foreach (string strOpenOrder in cmbOpenOrders.Items)
                {
                    if (strOpenOrder.Contains(" Table " + tbTable.Text + ","))
                    {
                        cmbOpenOrders.SelectedIndex = idx;
                        break;
                    }
                    idx++;
                }
            }
        }

        private async void btnOpenDrawer_Click(object sender, RoutedEventArgs e)
        {
            // Send command to open the cash drawer...
            bool bReturn = await Globals.OpenDrawer();
        }


        private void btnOpenItem_Click(object sender, RoutedEventArgs e)
        {
            // Present the "Open Item" dialog...
            OpenItemDialog oid = new OpenItemDialog();
            oid.Width = Windows.UI.Xaml.Window.Current.Bounds.Width;
            oid.Height = Windows.UI.Xaml.Window.Current.Bounds.Height;
            oid.CloseRequested += OpenItemDialog_CloseRequested;
            oid.init();
            dialogPopup = new Popup();
            dialogPopup.Child = oid;
            dialogPopup.IsOpen = true;
        }

        private void OpenItemDialog_CloseRequested(object sender, EventArgs e)
        {
            // Close the dialog...
            dialogPopup.IsOpen = false;
            // Add open item...
            OpenItemDialog oid = (OpenItemDialog)dialogPopup.Child;
            if (oid.bUpdated)
            {
                // Add item to order
                OrderData od = new OrderData();
                od.DisplayPrice = oid.openItem.col_Price.ToString("N"); ;
                od.MenuItemID = 0;
                od.MenuItemName = oid.openItem.col_Name;
                od.Price = oid.openItem.col_Price;
                od.OpenItemID = oid.openItem.col_ID;
                decCurrentSubtotal += od.Price;
                addOrderItem(od);
                // Enable the "Send" button...
                btnSend.IsEnabled = true;
            }
        }

    }

    public class OrderData
    {
        public OrderData()
        {
            FontColor = "Black";
        }
        public bool Discount { get; set; }
        public int DiscountID { get; set; }
        public string DisplayPrice { get; set; }
        public bool Exclude { get; set; }
        public bool Exclusive { get; set; }
        public string FontColor { get; set; }
        public int MenuItemID { get; set; }
        public string MenuItemName { get; set; }
        public int OpenItemID { get; set; }
        public List<OrderData> Options { get; set; }
        public OrderData Parent { get; set; }
        public int Portion { get; set; }
        public decimal Price { get; set; }
        public int SeatNumber { get; set; }
        public bool Sent { get; set; }
        public int SplitItemID { get; set; }
    }

}
